Compare commits
2168 Commits
dev-2.6.9_
...
wvp-28181-
Author | SHA1 | Date | |
---|---|---|---|
aa27d2080b | |||
e7339a5f78 | |||
5e982bfb02 | |||
24642eaa8a | |||
fb5f42baee | |||
abe3194c5f | |||
39a1a84961 | |||
c5b499a026 | |||
b20e48c911 | |||
55977b4a5e | |||
1e833d087d | |||
19524e9289 | |||
a3d4bf9899 | |||
fc60e18cfa | |||
fabc564fc8 | |||
c871fc5a61 | |||
7ad0709b0e | |||
e70c5f4cf3 | |||
bf0a4c2abf | |||
|
b079039f81 | ||
|
bf0efc2739 | ||
|
105ad25580 | ||
|
fc74ce9de4 | ||
|
68fbc8fef1 | ||
|
33b125262b | ||
|
f146203fd3 | ||
|
1245ae7874 | ||
|
3436e73e72 | ||
|
ab34cb37f3 | ||
|
9c3967d67a | ||
|
695f9b7f4d | ||
|
3d68b56bb5 | ||
|
241d223b8a | ||
d39b68b071 | |||
01622884a9 | |||
|
b3d21c7452 | ||
|
a9264a8bc0 | ||
|
e8770eec36 | ||
|
d68aebd409 | ||
|
5a3b1c04d6 | ||
|
97a87542a6 | ||
|
0e94aeaf5f | ||
|
07729fbe49 | ||
|
9a89cf81b8 | ||
|
79c8447298 | ||
|
46af350868 | ||
|
31df0fb3ff | ||
|
55b15f8ba6 | ||
|
cf8a1261b5 | ||
|
654599b659 | ||
|
47e5d2b00b | ||
|
782e8b9800 | ||
|
85f20df9de | ||
|
47526e241e | ||
|
ebc65b40d3 | ||
|
7f79b92568 | ||
|
88721511e7 | ||
|
9b62fbe467 | ||
|
13e2a96dae | ||
|
0371f5a96e | ||
|
674ab18c02 | ||
|
e5a9dd24ef | ||
|
18b5c73365 | ||
|
41c7137e3a | ||
|
2b2efb59a6 | ||
|
a23c1aca40 | ||
|
81a32fdb47 | ||
|
29f7a6b6eb | ||
|
64be28ed77 | ||
|
c25a99d60b | ||
|
28e060fd6f | ||
|
0c10c77a56 | ||
|
db493e2625 | ||
|
8874c90db2 | ||
|
1af6324a09 | ||
|
b15e559eae | ||
|
a74fb6ecd6 | ||
|
f3acf33fbf | ||
|
b6df13af24 | ||
|
a2cac5ca12 | ||
|
6120e6bd7b | ||
|
64b6a35603 | ||
|
d91583b833 | ||
|
e7e407eb57 | ||
|
9d61a93077 | ||
89c9d66e40 | |||
0c0ee3e7d9 | |||
|
76e8480cb1 | ||
6ee9f00bcd | |||
|
b3eb319e05 | ||
|
07b182da98 | ||
|
f8d2b933b1 | ||
|
7c07ae9421 | ||
|
33fba05a38 | ||
|
3ab4ce0a83 | ||
|
9ae520a58a | ||
|
ef58f29cfc | ||
cc896bb83d | |||
|
41fdb9d13f | ||
|
a380246e49 | ||
|
964d55431f | ||
|
c0b79878f4 | ||
|
67d1ff0d26 | ||
|
76d09bcadb | ||
|
18a9f86a0a | ||
|
7430c98309 | ||
|
d8011e9ee7 | ||
|
cb1f1417b6 | ||
|
01ecb07a2f | ||
|
0a245c4cfe | ||
|
df3f5795e7 | ||
|
3a1fc63d7a | ||
|
2397344973 | ||
|
04a1bfa329 | ||
|
b699158e43 | ||
|
eac72fd06e | ||
|
94edd95824 | ||
|
572c8850dc | ||
|
b4b9ad2873 | ||
|
42a2772d1a | ||
|
360fe689b1 | ||
|
5a9621840c | ||
|
e73d00060e | ||
|
7a52db4e89 | ||
|
083523d204 | ||
|
9f7dc295cf | ||
|
33506a0046 | ||
|
bdd1846eb4 | ||
|
92e5ed2e30 | ||
|
7e136c9ac7 | ||
|
ad36354ef4 | ||
|
fc77b3f819 | ||
|
0542700225 | ||
|
67e4060053 | ||
|
3d5842e9e2 | ||
|
dbf92b96b0 | ||
|
ffc8a530f3 | ||
|
29ef68038d | ||
|
db24f49275 | ||
|
c98ef23b98 | ||
|
9a572b97df | ||
|
a30ff222ec | ||
|
f78657473e | ||
|
8d7d751d44 | ||
|
b73747138d | ||
|
c1bc45fe8f | ||
|
a01295603a | ||
b52459846e | |||
|
58b333604d | ||
|
073b6acec3 | ||
|
f36eb7ebeb | ||
|
8bd2f47c9a | ||
|
f0d09d1808 | ||
|
8a9f8c6cab | ||
|
84c78be91c | ||
|
5cd2e2c41b | ||
|
5d3f307b44 | ||
|
941b9a8374 | ||
|
75fccfaf17 | ||
|
4ef1277c16 | ||
|
b7ad0a907f | ||
|
829ff200b8 | ||
|
f4f3e60a6b | ||
|
f9abbc7fe8 | ||
|
af911d4f02 | ||
|
47783946fe | ||
|
8fd87b335d | ||
|
da7889bf67 | ||
|
26ca854db5 | ||
|
99506108cd | ||
792b636898 | |||
0f58a59fbb | |||
|
e1d604a560 | ||
|
5ff2faa5bd | ||
|
79f3ca9791 | ||
|
cccfdace5b | ||
|
e11671a1fb | ||
|
ae9976bb3a | ||
|
16c056e338 | ||
|
2bb7e23601 | ||
133afc655a | |||
|
daac0010b1 | ||
5a30f6cd86 | |||
|
9b036fb71d | ||
|
92a25393f3 | ||
|
613399cc6d | ||
|
5a75381a00 | ||
|
90d9cd8ac8 | ||
|
7aa8444e67 | ||
e3d28ae139 | |||
f88ff28dc4 | |||
20db882bf6 | |||
45b3aa1368 | |||
|
4d62f77025 | ||
|
12c4128e81 | ||
|
e4d37864d1 | ||
cdc726999b | |||
0c1860368c | |||
|
124d83fc0c | ||
|
298a9f4280 | ||
|
78f628dd6f | ||
|
7d6aaf3bb0 | ||
98f1ffa838 | |||
5bbb8d2410 | |||
1f423acd56 | |||
1b3ba023ae | |||
a0d04ca7ff | |||
4d90fdd747 | |||
436d9ad9a7 | |||
8ab26c0cee | |||
cb94420806 | |||
58f950c207 | |||
aa55464a17 | |||
1d8bbd41e5 | |||
a623e7a387 | |||
af97ee8729 | |||
f1c4287611 | |||
|
f5d89e06a3 | ||
|
4084080a8e | ||
|
205f1f1f60 | ||
|
c084d6c98a | ||
|
4c28f380aa | ||
|
f6c1ce15e4 | ||
|
94a0de0d27 | ||
|
130dc5d82d | ||
|
32f1a0aa6e | ||
|
7620527340 | ||
|
483d5e04a7 | ||
|
e8411bc797 | ||
|
b9a33f03d6 | ||
|
da63ef5b19 | ||
|
a34db2ee8b | ||
|
4ba0e3c13e | ||
|
bc431e4290 | ||
|
e073b60cb1 | ||
|
2d11f1b3de | ||
|
2d423d9668 | ||
|
54038486f4 | ||
|
d05bce8f7f | ||
|
a6fb1cdb74 | ||
|
f57ed350b3 | ||
|
4f90b28b93 | ||
|
d02078397e | ||
|
212218c7c4 | ||
|
3cdede80f9 | ||
|
18aff4b546 | ||
|
33d4107d0c | ||
|
1d0c9c6a31 | ||
|
fd0ff18a71 | ||
|
0e9cb5ceb6 | ||
|
7155680793 | ||
|
73f6f044a1 | ||
|
bf8fbf4927 | ||
|
cde7f6460a | ||
|
a426b9bc53 | ||
|
44aef5d358 | ||
|
393d25f739 | ||
|
d38ccc257c | ||
|
d0ef68af3f | ||
|
e46f1ae915 | ||
|
9a64be46ba | ||
|
d739017678 | ||
|
e8b2ca4686 | ||
|
1b81080f6f | ||
|
dc37f66792 | ||
|
760b14eaaa | ||
|
4ae8c5ac3e | ||
|
3951a95284 | ||
|
23ce55260f | ||
|
49a8a08c94 | ||
|
8fab1ed0e8 | ||
|
b5ccb1636f | ||
|
b63a89a0a8 | ||
|
985082d339 | ||
|
9d56da5680 | ||
|
676a722241 | ||
|
91e49745e4 | ||
|
bac19f583c | ||
|
eefd6a0e21 | ||
|
66a76eadd5 | ||
|
dd2ae65786 | ||
|
4ca97d3174 | ||
|
6106bda151 | ||
|
d67f0a1ea4 | ||
|
5e34039def | ||
|
3e2486d0ab | ||
|
874a57387a | ||
|
0aada74b70 | ||
|
470625e077 | ||
|
6905f00293 | ||
|
f60494d641 | ||
|
fa13b22819 | ||
|
4a34097b68 | ||
|
988dc36fa5 | ||
|
ba884fa9ef | ||
|
a01086fe1c | ||
|
6797f77259 | ||
|
2e399faf41 | ||
|
bf1be52e7f | ||
|
e5cba6022f | ||
|
a4b15e84d7 | ||
|
735df5a935 | ||
|
a44adcab43 | ||
|
3de49d1c2a | ||
|
095a3e1384 | ||
|
e9a48e5303 | ||
|
59d8f2f915 | ||
|
51634b1b96 | ||
|
a4f6102a4f | ||
|
7fd34cfda5 | ||
|
8fdd10d1c2 | ||
|
17ea37506e | ||
|
d48f89eee4 | ||
|
0cb68938b8 | ||
|
97fef952ee | ||
|
7d7528cc27 | ||
|
a3d871022c | ||
|
bac9aca311 | ||
|
13811b0c78 | ||
|
48a1a24769 | ||
|
a39ac45bcc | ||
|
14efc4b855 | ||
|
77d9da25c4 | ||
|
9cd63f0105 | ||
|
41d9c347bf | ||
|
cb24ce13da | ||
|
19533c8f4d | ||
|
32c73ff595 | ||
|
5c49627012 | ||
|
7a120c6da4 | ||
|
3483980ada | ||
|
153523a32f | ||
|
86a20edb0b | ||
|
531fcb2a7e | ||
|
4f2cd41134 | ||
|
a9f88be8c5 | ||
|
287d42c196 | ||
|
4162706ec4 | ||
|
c42d391290 | ||
|
ef5018de2d | ||
|
668dc8f0dd | ||
|
9fc3db1f5e | ||
|
14eee911eb | ||
|
c27e345edc | ||
|
f525b55729 | ||
|
04e7f48fde | ||
|
468e2b2ffb | ||
|
885842249f | ||
|
ff1e9f79c2 | ||
|
9fc9a29811 | ||
|
fd434b3cf2 | ||
|
e4754af417 | ||
|
e163cf4d20 | ||
|
61e5226122 | ||
|
0a3d25fb5b | ||
|
deeff5533b | ||
|
457c5e3821 | ||
|
733a11f265 | ||
|
43ef195543 | ||
|
ba8fffd907 | ||
|
e4622d17a6 | ||
|
27b125cf98 | ||
|
64cd48a92b | ||
|
01bc6c857e | ||
|
8237cd25af | ||
|
228c57399a | ||
|
b64f320805 | ||
|
c916433042 | ||
|
18ad50222f | ||
|
2d4bbbea8e | ||
|
0592fd676f | ||
|
7f0be280c3 | ||
|
e8b766172e | ||
|
f62bf7b2c6 | ||
|
1294081a9c | ||
|
bfae9780f7 | ||
|
def56793ba | ||
|
639e0bab11 | ||
|
a77628e875 | ||
|
ed035b74d9 | ||
|
6fcff0567e | ||
|
c7d1515023 | ||
|
724963324a | ||
|
fec69c714c | ||
|
7749ea3421 | ||
|
cec266d3cd | ||
|
f306937616 | ||
|
155838ce2e | ||
|
f4e5e03962 | ||
|
7b24d51db9 | ||
|
3350b65259 | ||
|
96d2a27d41 | ||
|
a7bf29a4cb | ||
|
fa62ab9a01 | ||
|
9e28923b8c | ||
|
b4dadf6c51 | ||
|
21a96ad20f | ||
|
d310204d00 | ||
|
0532363192 | ||
|
6b3732b8c4 | ||
|
8cf5b65e38 | ||
|
8942ab0112 | ||
|
ccc0a99d68 | ||
|
652489b47e | ||
|
05cc0d14f1 | ||
|
15df08964b | ||
|
319cdd2151 | ||
|
138216c395 | ||
|
5b8ffd5b61 | ||
|
f4960b2618 | ||
|
f3388dd53a | ||
|
e68eb850a9 | ||
|
c4d7dd9651 | ||
|
8f5bbfa5c2 | ||
|
fa80ba6f2b | ||
|
52f9c295f9 | ||
|
446f729e55 | ||
|
d93947c657 | ||
|
1bdc0621b8 | ||
|
a2d93fce81 | ||
|
03f3598681 | ||
|
20a47729fc | ||
|
095b12ebbd | ||
|
ca715e0234 | ||
|
0c14970ab8 | ||
|
534be3f580 | ||
|
e272fa26e1 | ||
|
b7f2a6b25b | ||
|
97b04c4dba | ||
|
db3240d918 | ||
|
2ef4111297 | ||
|
b7d85a270e | ||
|
8d6de72429 | ||
|
74431b1e98 | ||
|
dbdb9ca06d | ||
|
614eaa8f4f | ||
|
0c5b30e74f | ||
|
51c19c397d | ||
|
c2ef001546 | ||
|
7d5a5b6c8f | ||
|
ffb21248cb | ||
|
314423bd01 | ||
|
9ff1613d3b | ||
|
50240b4e39 | ||
|
5a152791c0 | ||
|
57192a49d1 | ||
|
6bbac849b3 | ||
|
d0083447bb | ||
|
a91fe69f76 | ||
|
5639719879 | ||
|
d72c1c0c4c | ||
|
5632718d6f | ||
|
5ebd788cef | ||
|
6d52e1539f | ||
|
31c2f52e48 | ||
|
babc0f79cb | ||
|
807d0524a6 | ||
|
061749548c | ||
|
e3225d4844 | ||
|
9e790eb0ff | ||
|
be9bf60e81 | ||
|
e42d015729 | ||
|
ca103731c7 | ||
|
23b8667b7f | ||
|
5d40080468 | ||
|
512b0cc8f5 | ||
|
cf48bd95ff | ||
|
b498e2fcf2 | ||
|
d849352441 | ||
|
b726dc9753 | ||
|
ccecda7859 | ||
|
21258d6ba3 | ||
|
a2da81f79a | ||
|
7e48d84740 | ||
|
affbd89fdb | ||
|
c429a34e53 | ||
|
98bd8913e7 | ||
|
490c55381f | ||
|
e2f9ee8f7b | ||
|
9ccce01692 | ||
|
381c3bdc20 | ||
|
2bc2842224 | ||
|
3fe47021b9 | ||
|
adbddd5eb0 | ||
|
b1fb1c4616 | ||
|
ebc904e4d5 | ||
|
97b673d6ad | ||
|
813fd772d1 | ||
|
8ef5e2618d | ||
|
c561dda269 | ||
|
8a68bae0bb | ||
|
cb897aaeed | ||
|
94da74901c | ||
|
ea3f899593 | ||
|
b944f8867c | ||
|
269ad8cedb | ||
|
22deb206ba | ||
|
5c3c3e6a4c | ||
|
d6262acf6a | ||
|
25b400cbe3 | ||
|
0f50904992 | ||
|
c56538813e | ||
|
0f3898910c | ||
|
f68f6d20e0 | ||
|
db2ccfedfa | ||
|
08a20f907b | ||
|
03070db3fc | ||
|
30ad3fca99 | ||
|
cbd8b074af | ||
|
f5d07c4c14 | ||
|
cf1696e0d6 | ||
|
d46fc9de82 | ||
|
1f02cb9178 | ||
|
ede2c5005d | ||
|
71030ca6bc | ||
|
cef04a8b5a | ||
|
72f59e1cd4 | ||
|
5c5699ae11 | ||
|
88779b983e | ||
|
15f718bd64 | ||
|
e3d7be9d81 | ||
|
403f1e16a3 | ||
|
8c4922cbe1 | ||
|
0858f7995b | ||
|
bc5cf6f5bd | ||
|
e21e419361 | ||
|
59ab2adb2e | ||
|
f89ef3abf4 | ||
|
3dfbc843ad | ||
|
4f2d47385d | ||
|
053cd130aa | ||
|
056162d742 | ||
|
e166cc366c | ||
|
c953943083 | ||
|
1421b4743c | ||
|
2e5d94181a | ||
|
8a590d5c39 | ||
|
ed5dde81f6 | ||
|
6c969a63dd | ||
|
3227dcd082 | ||
|
91bfbc36f1 | ||
|
58d1f0ea16 | ||
|
3b1516afe5 | ||
|
4f22994cdb | ||
|
193e1a24a1 | ||
|
a4328e3d4f | ||
|
663f394177 | ||
|
f210952ed2 | ||
|
de969b7760 | ||
|
c85c994972 | ||
|
66234dc288 | ||
|
df9f6a8927 | ||
|
713aa00acc | ||
|
219f863191 | ||
|
aac3e95159 | ||
|
3fd60f8676 | ||
|
0f3f3c077b | ||
|
bc7cc73d52 | ||
|
b444585ebe | ||
|
c73fe2b0cf | ||
|
3ef643d658 | ||
|
3ae0878ec2 | ||
|
dbb4a20602 | ||
|
ed08c7ef77 | ||
|
8773864b5b | ||
|
ccbef9b533 | ||
|
2c3f6417a3 | ||
|
4172e6c64b | ||
|
3e4d2b682c | ||
|
fe9965bc63 | ||
|
0772f69885 | ||
|
7bfaaf8838 | ||
|
b5efaa7baa | ||
|
eb173b1b24 | ||
|
782300452c | ||
|
d3027b0668 | ||
|
22a205e8fc | ||
|
c3ce2bc5d0 | ||
|
72b9239c5a | ||
|
eec4e347d7 | ||
|
85c5fafda5 | ||
|
5cd3e0e919 | ||
|
71cf9852ec | ||
|
bb3f219a61 | ||
|
2bf07305aa | ||
|
be6666db03 | ||
|
efbc3a31c0 | ||
|
5fab97cf7e | ||
|
8c2b1ef4fe | ||
|
08c2fa45f7 | ||
|
bea5b40bf5 | ||
|
e3be796314 | ||
|
943f95ba8c | ||
|
84595e0c84 | ||
|
bdcd006a7e | ||
|
292c36f1c1 | ||
|
95688e400b | ||
|
273b282af6 | ||
|
14c4a3c7e8 | ||
|
ec90519c90 | ||
|
b16923d175 | ||
|
cefdce5e0a | ||
|
c5ff811378 | ||
|
048a6ce072 | ||
|
a7c3cf5316 | ||
|
8acd64eac6 | ||
|
2177e9dbf9 | ||
|
c662a53098 | ||
|
a5d9afeb60 | ||
|
a0cdc7c59d | ||
|
9c34978963 | ||
|
6afcd5176b | ||
|
845ce53313 | ||
|
2d2832dbe9 | ||
|
4446218f9e | ||
|
21d5bed1a9 | ||
|
d0532e7749 | ||
|
307a68de73 | ||
|
9dcae6e4bf | ||
|
f7b67e28cc | ||
|
7c019dbeef | ||
|
b13ecc578c | ||
|
842f40df34 | ||
|
7be636f8b8 | ||
|
2c7ed82b3e | ||
|
bdc0f83e29 | ||
|
81da03d981 | ||
|
d79eec25b0 | ||
|
39199a1daa | ||
|
342361cef8 | ||
|
b010e63dc0 | ||
|
e0c8216f58 | ||
|
48fad3582d | ||
|
03ee15ece2 | ||
|
5462b1f6c6 | ||
|
6484f52e46 | ||
|
c2e26291ce | ||
|
55ee6f5f0d | ||
|
e46bf8a8bd | ||
|
375cd03575 | ||
|
aa3cec0dfc | ||
|
25fca14e62 | ||
|
fdd732250a | ||
|
a5ed284658 | ||
|
d50dd3fe84 | ||
|
9586f58a30 | ||
|
40ece192fe | ||
|
0a380c6ff9 | ||
|
e5b1876012 | ||
|
7a9f001dcb | ||
|
6246ce6ba8 | ||
|
b89e46871a | ||
|
192f012829 | ||
|
8f2ce95165 | ||
|
166272ad11 | ||
|
7470e1fe8e | ||
|
d395f5d6c0 | ||
|
fb4336c5e0 | ||
|
2b1f7a4739 | ||
|
2d492c5b6b | ||
|
df7171353b | ||
|
bdf799fb64 | ||
|
44b250eed2 | ||
|
aedbc4ed75 | ||
|
f3e4928995 | ||
|
10be210b57 | ||
|
6374a8f2e5 | ||
|
ca1d66cfb8 | ||
|
141b228267 | ||
|
c19ad94c3e | ||
|
ebcd2320a9 | ||
|
e2944938cd | ||
|
955c893428 | ||
|
fb8a5d483b | ||
|
d4fdea3df9 | ||
|
e429c9f5a7 | ||
|
4babf2b47b | ||
|
26cd7dbaf9 | ||
|
72a1f12208 | ||
|
8b0662ebfe | ||
|
88878940af | ||
|
9b9a13ab36 | ||
|
fd3a4ef472 | ||
|
d03e8b0428 | ||
|
09a23bc80e | ||
|
72132ca70e | ||
|
ce035dbcdb | ||
|
809e4c98c5 | ||
|
a82b831b8b | ||
|
7b601a3e8f | ||
|
37e973949f | ||
|
09bfc69f07 | ||
|
6e4d9d9749 | ||
|
aa71a33c38 | ||
|
276f077dc7 | ||
|
c8524b1d43 | ||
|
c1145a8163 | ||
|
1516991372 | ||
|
5606bce885 | ||
|
131ea77669 | ||
|
850260ec28 | ||
|
142b17cc76 | ||
|
1bb48e221b | ||
|
b96d580168 | ||
|
8f39254dd0 | ||
|
2d8f57f3c9 | ||
|
170b0a1800 | ||
|
1cc111a573 | ||
|
ef6693aabb | ||
|
3aabbd6919 | ||
|
9b8c1ad8c6 | ||
|
14151c07e3 | ||
|
d60452560e | ||
|
f89491ada3 | ||
|
fb957b0dba | ||
|
bdd9ff1fd7 | ||
|
0629d4cf0d | ||
|
fa2ccb4ec8 | ||
|
278264a2c6 | ||
|
8ea6e192d9 | ||
|
1469971102 | ||
|
1983b8b0a7 | ||
|
8cab9f23b0 | ||
|
86c08db266 | ||
|
a02883b394 | ||
|
946e1dc245 | ||
|
a53dce38c2 | ||
|
5f7c53823a | ||
|
6b8ecd1f9d | ||
|
23710f1c64 | ||
|
d340a37a00 | ||
|
c04de4cd70 | ||
|
694076dc8c | ||
|
2466a24860 | ||
|
8870f5f5a1 | ||
|
eb2a4139fa | ||
|
96bb3814f6 | ||
|
c62a8986dd | ||
|
cc4c4ac144 | ||
|
73c7dab47f | ||
|
d040254430 | ||
|
f4ee7271e7 | ||
|
4c8e2beb4d | ||
|
f762e03f0b | ||
|
ab909feedf | ||
|
aae7c80fd5 | ||
|
189b6044b4 | ||
|
3e71e0bdf1 | ||
|
0815b8e130 | ||
|
fb1d9ca50a | ||
|
6e5f04b368 | ||
|
7a41f66e8b | ||
|
c56258ba8a | ||
|
aed45e0f0d | ||
|
1ab73f69eb | ||
|
f3454caaf6 | ||
|
662a70e20f | ||
|
0f0ece2401 | ||
|
958474c646 | ||
|
ca891f367c | ||
|
d6fe626b1c | ||
|
3ffe205082 | ||
|
2bf7cdc2df | ||
|
95d367702a | ||
|
6dbc7a68bd | ||
|
b25f3631ee | ||
|
b6bcb5f2f4 | ||
|
b64d701f37 | ||
|
c5b16e058d | ||
|
7bfa85424a | ||
|
84c60381cc | ||
|
f9ae4cfdbe | ||
|
1af77ab5f7 | ||
|
e9a7207e1f | ||
|
b0d0d30781 | ||
|
5327a85739 | ||
|
869c2f20f2 | ||
|
55b53caef1 | ||
|
e33e6a942c | ||
|
86b56ccc6d | ||
|
74714711aa | ||
|
1beb220b5b | ||
|
8228f59cb1 | ||
|
688e222dcc | ||
|
470be2dc36 | ||
|
72e91f693c | ||
|
4c66f6b29e | ||
|
c9fd7f940f | ||
|
cd626ac2d7 | ||
|
3c52a16e5f | ||
|
882e6a027e | ||
|
878dc33e6b | ||
|
80d2edeef2 | ||
|
58b9dab89f | ||
|
22441ad5a1 | ||
|
20cd60c66c | ||
|
3e91483d4b | ||
|
42838a176c | ||
|
7918f03734 | ||
|
1e1364e51a | ||
|
2f11618199 | ||
|
0ff4ed217d | ||
|
4f2191dc9f | ||
|
c4fc4abf7c | ||
|
4a0037d128 | ||
|
dabee4ed7d | ||
|
ad246bf921 | ||
|
5bf1fe84ec | ||
|
92022f8a8b | ||
|
a463b676e2 | ||
|
b19a885f1d | ||
|
c18dd55c74 | ||
|
a4f48a1522 | ||
|
386b48192d | ||
|
6ae33f2a67 | ||
|
30979eb6ea | ||
|
3fb9694c2d | ||
|
bf97908c5e | ||
|
0cc5917d8a | ||
|
559fbf1258 | ||
|
d176b5231b | ||
|
d7355a671b | ||
|
2ea1bc8ae1 | ||
|
4c6c77be7a | ||
|
cd117ed228 | ||
|
e44e3dc940 | ||
|
b79a49fa76 | ||
|
fc7f1b3459 | ||
|
a574ff0944 | ||
|
70c20364af | ||
|
1abfced3b4 | ||
|
5e73874880 | ||
|
710600db6f | ||
|
1ee56d50d8 | ||
|
692f716788 | ||
|
7462e2776b | ||
|
5b3dc4d595 | ||
|
12571e0db1 | ||
|
250a059ca0 | ||
|
243edbd143 | ||
|
221f99c764 | ||
|
b5fb82934e | ||
|
bd5b9ca1f7 | ||
|
feb9996538 | ||
|
394c40d8bb | ||
|
4bda14b098 | ||
|
a6f9c090cb | ||
|
6a5ab117f5 | ||
|
f1c7d612ca | ||
|
60c4f767f0 | ||
|
ec0ec5eb54 | ||
|
3884e9a56a | ||
|
e7bdcc1f8d | ||
|
d5e8aa62a1 | ||
|
0134488428 | ||
|
ee7ef0bf41 | ||
|
7db2bf7b51 | ||
|
b46e5efad2 | ||
|
3146e63fc0 | ||
|
703c2e292a | ||
|
275b272160 | ||
|
2de4c322f6 | ||
|
d47902bdca | ||
|
9e2630ee32 | ||
|
6e90050db4 | ||
|
8b6449ce3a | ||
|
9f680a2e9e | ||
|
fa06602910 | ||
|
d66aab2e83 | ||
|
0a404e2389 | ||
|
938064199b | ||
|
3c025a5ac0 | ||
|
942c5caa7c | ||
|
f24b6fa13f | ||
|
89a2e62702 | ||
|
977bab158b | ||
|
042b28b2d6 | ||
|
5461b8ebf2 | ||
|
ecd14d6757 | ||
|
4ee8924bd9 | ||
|
117387be8f | ||
|
7f05c91176 | ||
|
1a9e49d9ff | ||
|
8f77d0c25c | ||
|
b67841b319 | ||
|
e666bb0407 | ||
|
59bda74e88 | ||
|
4fe5672623 | ||
|
470aa47969 | ||
|
c041aaccb4 | ||
|
2591997dfc | ||
|
dab04fcab7 | ||
|
82ab6b1760 | ||
|
eb177a6742 | ||
|
871b4e5359 | ||
|
a88518f8b5 | ||
|
842be1a485 | ||
|
af9dd1800b | ||
|
fa126a76a9 | ||
|
935221ab41 | ||
|
a580ff6fbd | ||
|
7ecc86b33d | ||
|
3b5a37c270 | ||
|
28df05e261 | ||
|
d21d281b2c | ||
|
c273a6aa5a | ||
|
3adc81764c | ||
|
d94ceb4fed | ||
|
231582eb77 | ||
|
142efdd915 | ||
|
d09d8f11f0 | ||
|
3496ca2378 | ||
|
f93a0d599e | ||
|
97d4599390 | ||
|
5e4a673ecc | ||
|
2a5c12746b | ||
|
a59095db0c | ||
|
e05d0aa0a9 | ||
|
0e38e743ce | ||
|
646c3e41b7 | ||
|
778969f1eb | ||
|
fd091e545b | ||
|
34f2832bef | ||
|
fff3d64f85 | ||
|
f84eebdb75 | ||
|
d891b89c4b | ||
|
c7e09589af | ||
|
bc38f5ef29 | ||
|
76dedb11f8 | ||
|
b957ab61c7 | ||
|
c77c1a956c | ||
|
91dc4566a2 | ||
|
8ee7211ba3 | ||
|
e29d94c83f | ||
|
eefe6f4c8d | ||
|
f66bf823fa | ||
|
8d87741dea | ||
|
a51b411101 | ||
|
fc0ad32f81 | ||
|
9e397ba9f6 | ||
|
7f5a18d6b5 | ||
|
4a43d04020 | ||
|
28b5cc39d0 | ||
|
03864ae46f | ||
|
4765f9b9f2 | ||
|
2b351e1e18 | ||
|
c48def08cf | ||
|
1002150b2a | ||
|
c6fbd03276 | ||
|
4d1c6401c2 | ||
|
a509587980 | ||
|
4451994959 | ||
|
fc89b7b517 | ||
|
be5dbc9a21 | ||
|
81f69eb6f4 | ||
|
0b1cae75fe | ||
|
74d97734ba | ||
|
1a1a68784b | ||
|
afbec28906 | ||
|
44b06e1b6e | ||
|
fcd79b9864 | ||
|
5e724cc062 | ||
|
d7c293c867 | ||
|
8aa0bdf539 | ||
|
10cb58391a | ||
|
5d673fb033 | ||
|
f5fcc79a2c | ||
|
0da452293f | ||
|
59e0767179 | ||
|
23bd11869b | ||
|
c239ee277c | ||
|
5e5437b630 | ||
|
4b4afa4ef7 | ||
|
6c919937bd | ||
|
519a08e530 | ||
|
2a792fffb4 | ||
|
9bb61a70ab | ||
|
1e105fb6e1 | ||
|
0c4a8c0975 | ||
|
0e18a163ac | ||
|
4d2c36edcd | ||
|
74365144aa | ||
|
8eff2f1d11 | ||
|
3d6db7478d | ||
|
072e84db19 | ||
|
ddfe4a7b2d | ||
|
39a5c8e2cf | ||
|
c2faa8c3ce | ||
|
dbe6ece653 | ||
|
f7006e4881 | ||
|
f760134b39 | ||
|
0e826e3448 | ||
|
8f7db635a3 | ||
|
a9c4638c94 | ||
|
5fae9a7b34 | ||
|
c801ee6218 | ||
|
31a8e6ea89 | ||
|
9ce6045f56 | ||
|
c022213972 | ||
|
be9533dead | ||
|
dfd1d257e2 | ||
|
e0344ccf97 | ||
|
c827d1518b | ||
|
6d4312e383 | ||
|
8a362506c6 | ||
|
cba2e6b90b | ||
|
d3e815bf16 | ||
|
5df95ba850 | ||
|
19a52a20f3 | ||
|
acac24f0db | ||
|
47abdde339 | ||
|
d88c95f409 | ||
|
9ae0691c80 | ||
|
936adf31fe | ||
|
ed2680bf03 | ||
|
9a0ea9e322 | ||
|
8555d64f95 | ||
|
cf35daeb98 | ||
|
0e2908c1be | ||
|
f09f1c9a2a | ||
|
eda9bafd77 | ||
|
0cd9a20242 | ||
|
2a5404c68f | ||
|
dc6769664e | ||
|
632630817b | ||
|
0726bca36f | ||
|
f513f5ef67 | ||
|
4e13489366 | ||
|
3c48ef8f43 | ||
|
46c77302a1 | ||
|
7a917ee50a | ||
|
a4a0394f6b | ||
|
6cee5a0751 | ||
|
cb845726f6 | ||
|
72852799fc | ||
|
d739bfa597 | ||
|
07fa589e06 | ||
|
3aa2665fb2 | ||
|
590358c313 | ||
|
78fac69cd5 | ||
|
fe576c5838 | ||
|
7bb38c5c7b | ||
|
d202291aa8 | ||
|
973e75f808 | ||
|
1e75b2567f | ||
|
9ef1a0277b | ||
|
491286095c | ||
|
6fbac144d6 | ||
|
0ad8a11d8d | ||
|
ff83f2c7c8 | ||
|
36e3398b76 | ||
|
17f219d351 | ||
|
b9ffcd1d38 | ||
|
3051fc82ee | ||
|
1d753b48c0 | ||
|
debfb2222f | ||
|
bfb3b4ea13 | ||
|
e6790d88fc | ||
|
e541341504 | ||
|
850f20143f | ||
|
bbf8ab9310 | ||
|
9a80e10f6e | ||
|
95642d0bb8 | ||
|
98e6cf5bae | ||
|
d571e44040 | ||
|
4d3f0a8d79 | ||
|
1757203202 | ||
|
95b1cbba65 | ||
|
ec749de7c1 | ||
|
4199650c20 | ||
|
0781d9bc28 | ||
|
2d7a202096 | ||
|
a030d00c88 | ||
|
3cd1378d39 | ||
|
715ecb1d64 | ||
|
f6893cf95b | ||
|
6bab3b6740 | ||
|
c395cf42d1 | ||
|
a1321c29c5 | ||
|
93e6347f18 | ||
|
bd21d0e391 | ||
|
ec8ab540f8 | ||
|
36170df3f4 | ||
|
a8097c35da | ||
|
88db57697a | ||
|
523139143f | ||
|
a2182b5a7b | ||
|
cc63a52884 | ||
|
e218553685 | ||
|
afe2450a14 | ||
|
ee62f17170 | ||
|
04f938ef62 | ||
|
3469694ed1 | ||
|
c8831bc58f | ||
|
bfaa519e49 | ||
|
5d901b5e3f | ||
|
c286ecb455 | ||
|
7f0ca85850 | ||
|
ff3c30f32e | ||
|
05a324a07a | ||
|
c592740efa | ||
|
260bfd5935 | ||
|
db865cc9cc | ||
|
c4a2854e1b | ||
|
d679a9fcf8 | ||
|
a0537d74df | ||
|
f6fa1eed6c | ||
|
e0d641064a | ||
|
2e90c7e7fe | ||
|
a53fe7761f | ||
|
35b3d7618d | ||
|
420a87cfd7 | ||
|
4e0a463f88 | ||
|
effe71640d | ||
|
102aad1f5d | ||
|
363606d845 | ||
|
9ce22eba3c | ||
|
6c719556f5 | ||
|
62f5b3dfdd | ||
|
c88b0a8bd6 | ||
|
5c1a5f7931 | ||
|
1484c14130 | ||
|
0b6b72ae44 | ||
|
a012007f36 | ||
|
26c3ca6a21 | ||
|
d4b05c11c0 | ||
|
5dc08a45f8 | ||
|
9fb7246fec | ||
|
bea61f909d | ||
|
7f965a6922 | ||
|
b81660536c | ||
|
6e7cd084ee | ||
|
44b7f67a20 | ||
|
6e4fc1e79b | ||
|
9ab99edc1e | ||
|
e7ab983f94 | ||
|
33eec2b68f | ||
|
2bc43f4262 | ||
|
1e10524ba4 | ||
|
1179a7ad02 | ||
|
92421b46cc | ||
|
909d08a9d9 | ||
|
1e2d207aea | ||
|
fc97febe1d | ||
|
7d1116c892 | ||
|
190fc62b72 | ||
|
3501046ebe | ||
|
2735a7a98b | ||
|
5623b5ee0f | ||
|
fb843d41c1 | ||
|
d7bfd9bfa7 | ||
|
a0462055de | ||
|
3def634a27 | ||
|
acd767b47a | ||
|
4dcc7df555 | ||
|
f7236c4a90 | ||
|
7145ce07e6 | ||
|
f635f9c300 | ||
|
088419b4d8 | ||
|
4d975c21da | ||
|
9466bf5863 | ||
|
91515f1b05 | ||
|
93d69d5476 | ||
|
6bb8f45e27 | ||
|
20622d20d6 | ||
|
596a633d2e | ||
|
b8bb9c1b74 | ||
|
c1f6401598 | ||
|
d36920c699 | ||
|
22e1d92a9d | ||
|
0dc1807f62 | ||
|
25102229f6 | ||
|
eef78c7873 | ||
|
40a806329c | ||
|
e6ee7fe747 | ||
|
efc4a7bc8e | ||
|
3955e6ed53 | ||
|
c2e2e24551 | ||
|
40fb794798 | ||
|
fcf8c40150 | ||
|
ba8633e99a | ||
|
81f1b8ee25 | ||
|
f10b458fc9 | ||
|
f1c8ca602d | ||
|
8553769e76 | ||
|
7ad28af0e3 | ||
|
76226c414d | ||
|
f7e39141db | ||
|
c9f091d560 | ||
|
3eef73ecb6 | ||
|
c3b47fa734 | ||
|
d42329a021 | ||
|
5ed44c3e09 | ||
|
d883de7f9a | ||
|
2659f10551 | ||
|
4ac63a158d | ||
|
7e755f405d | ||
|
cb80119090 | ||
|
b0e494b842 | ||
|
ee490f5b93 | ||
|
0de634cdf7 | ||
|
1553b39b45 | ||
|
fb977546f3 | ||
|
cec21940f7 | ||
|
a2b873c14e | ||
|
52cd02de51 | ||
|
c23a529296 | ||
|
60278ee6ad | ||
|
a1b6e56427 | ||
|
9aee7d42e3 | ||
|
daab2586ca | ||
|
7d9cc96ef5 | ||
|
e9586687f7 | ||
|
a77ba194ad | ||
|
2142b7ffcd | ||
|
bc1b8098a2 | ||
|
b565523684 | ||
|
7af3cb03ec | ||
|
59ef6e67d3 | ||
|
c8f9f19c38 | ||
|
4a0fd9ead3 | ||
|
57e6cdefdf | ||
|
bf10cc1b35 | ||
|
69d9692f61 | ||
|
ba3c38d7d3 | ||
|
b1c479b938 | ||
|
e752dbd1a7 | ||
|
691313b778 | ||
|
66aac4526b | ||
|
d21a00418e | ||
|
70ada79c7a | ||
|
0dfce85d2f | ||
|
ea08969bfc | ||
|
0e69251281 | ||
|
11d40d3e22 | ||
|
42901d0374 | ||
|
28e5c1ae05 | ||
|
28b1ed8b0d | ||
|
bde0e13682 | ||
|
354a39961a | ||
|
1171cf1ea9 | ||
|
61e91afd91 | ||
|
1c95f1b4aa | ||
|
5cfaad2d6d | ||
|
4a22611320 | ||
|
98d12ecd6b | ||
|
45e9fc880c | ||
|
1cb2b2cc5f | ||
|
4e3247e44e | ||
|
c1d7f867c2 | ||
|
5e272330c2 | ||
|
4abbf4df07 | ||
|
a948b38dd6 | ||
|
f88c70d38c | ||
|
d474bf929e | ||
|
bef7fb2440 | ||
|
3b5ce2e4d1 | ||
|
ec97c6a7d0 | ||
|
bea63f67e7 | ||
|
335916f1f1 | ||
|
41616f726d | ||
|
21506440d2 | ||
|
a45bb7d9df | ||
|
ca79100b6f | ||
|
b2c953fc76 | ||
|
9d37b411ec | ||
|
cbea5f64c9 | ||
|
bb50a24314 | ||
|
3dc1e0368e | ||
|
ee746e53cd | ||
|
50c2a5a728 | ||
|
cadd0ee038 | ||
|
83671d8f10 | ||
|
16e8aa323f | ||
|
1f39c6c62f | ||
|
b10a65483d | ||
|
e5370bbd6e | ||
|
d21322a932 | ||
|
01a619f9e3 | ||
|
28d7fd3b58 | ||
|
14174ff400 | ||
|
b019106c44 | ||
|
2eb1ca2d94 | ||
|
af885ca4d9 | ||
|
b225b53510 | ||
|
6a4cdc36b1 | ||
|
d73630c49f | ||
|
128ccc7ff7 | ||
|
0993bedb46 | ||
|
bbb808d83f | ||
|
ae83bd6d06 | ||
|
94af90fa14 | ||
|
1dcdbc3742 | ||
|
f5640fddb7 | ||
|
8f9a530296 | ||
|
fe0b5c33f9 | ||
|
86f87c4665 | ||
|
e66b839659 | ||
|
29191373aa | ||
|
298d104fec | ||
|
1ea95d2b87 | ||
|
4c53b10737 | ||
|
97698ee716 | ||
|
347eec086d | ||
|
bb1fada32c | ||
|
b1d4123d29 | ||
|
e4e0cde16c | ||
|
9c5b1060af | ||
|
6d454423a2 | ||
|
0cd86a79c2 | ||
|
e94b99d11c | ||
|
f65d2730e0 | ||
|
917e2b577d | ||
|
c3c44dbd53 | ||
|
560165b667 | ||
|
f97ce3e936 | ||
|
f52be30399 | ||
|
10f776678e | ||
|
7400ace65d | ||
|
0cc0a21206 | ||
|
ce56d9c0bf | ||
|
b97db305eb | ||
|
777f2e2121 | ||
|
e0f8acf09f | ||
|
7852c4fde7 | ||
|
c8b9e590ef | ||
|
c9bfdf2525 | ||
|
00afecac47 | ||
|
a42dda2bd3 | ||
|
0191e93768 | ||
|
f4c03c1808 | ||
|
e861c9dfab | ||
|
2157bb0270 | ||
|
0a44eb8965 | ||
|
0b6587b1ad | ||
|
5bcd8495e0 | ||
|
b7635ec05d | ||
|
0327d16021 | ||
|
59c79c08e1 | ||
|
b0d3bf3ed9 | ||
|
9442c37ce7 | ||
|
d4fe0fb325 | ||
|
5528517471 | ||
|
54df5df031 | ||
|
b663a8ab41 | ||
|
980052015a | ||
|
bf66f8f694 | ||
|
59f0210d04 | ||
|
37a84e6691 | ||
|
0209dc89c9 | ||
|
d07a5680f3 | ||
|
e0028a87cb | ||
|
ea85a620d1 | ||
|
d7afcab601 | ||
|
8d5764b9a0 | ||
|
646419e4ad | ||
|
8cfff8db97 | ||
|
f33c3a3630 | ||
|
66cadafd1c | ||
|
89db9991a2 | ||
|
9b21fba871 | ||
|
e728233781 | ||
|
f9b8ea6573 | ||
|
7cb74dbe51 | ||
|
d34be408d6 | ||
|
75ee368c96 | ||
|
c547851487 | ||
|
abc65c6317 | ||
|
08468edd45 | ||
|
5c2d27f75d | ||
|
1dbb559b38 | ||
|
4065703317 | ||
|
94688534f8 | ||
|
5f7fa2784e | ||
|
2e60339e0a | ||
|
a179a45ac3 | ||
|
46cf650a86 | ||
|
b6702f7c05 | ||
|
3f5e885e82 | ||
|
7d88827415 | ||
|
c5ddf59858 | ||
|
bc710b6f1b | ||
|
6ba8ab22b5 | ||
|
e8090bc84c | ||
|
9be861abcc | ||
|
59e3a280d6 | ||
|
baef2dd13d | ||
|
fa346513db | ||
|
385fdb95f1 | ||
|
b90969f180 | ||
|
29d69267f9 | ||
|
ad4afd9d67 | ||
|
b7c16fe6ed | ||
|
4bd4f50b41 | ||
|
06e22d980e | ||
|
c6202b3b27 | ||
|
ac1a4a027a | ||
|
36fda97ebb | ||
|
cf23816c80 | ||
|
bfcb4d2335 | ||
|
f99c9cac6a | ||
|
098dd8a045 | ||
|
abb60593cb | ||
|
ddb36e54bd | ||
|
458e7d18b7 | ||
|
cea7d51139 | ||
|
dc20ccfce8 | ||
|
6e0f7fae6e | ||
|
7e428f8231 | ||
|
e53ce59166 | ||
|
fab21b3660 | ||
|
33ddf707b5 | ||
|
206f47f42a | ||
|
726963ba77 | ||
|
7241e0d2d2 | ||
|
a4c93cf613 | ||
|
89956873d7 | ||
|
344692640c | ||
|
2385f4b30c | ||
|
22efd0f56c | ||
|
4418c62e5c | ||
|
01519c2574 | ||
|
cf8e40c152 | ||
|
b0cc14051c | ||
|
1401ce98d4 | ||
|
3962352ec3 | ||
|
bc82662e90 | ||
|
0c10e8d9d3 | ||
|
0eba7c40c3 | ||
|
20fdd99670 | ||
|
bc0319b3f3 | ||
|
b6fa459bc3 | ||
|
20a3cb9e73 | ||
|
faac93613a | ||
|
010b09674c | ||
|
2166ec9362 | ||
|
ab81136765 | ||
|
9b1af8ef13 | ||
|
a2f0854138 | ||
|
381b3d15ca | ||
|
2753e1acf3 | ||
|
86cd03ce70 | ||
|
d68f9c8133 | ||
|
5b0b17d741 | ||
|
52656bb893 | ||
|
241804f5f8 | ||
|
42d8fff574 | ||
|
963a74d280 | ||
|
2bac0b3c22 | ||
|
a797cd1c4b | ||
|
2a1f979651 | ||
|
a1398a56cc | ||
|
ffb0fcb907 | ||
|
a0c7b35e1d | ||
|
7371db4674 | ||
|
6ac131bcf6 | ||
|
0984290ca2 | ||
|
a16b4f71ec | ||
|
f89672757a | ||
|
fb9678e9d3 | ||
|
b4e7ed0bf7 | ||
|
019827fd35 | ||
|
3c0dde2f3c | ||
|
83bdb9117f | ||
|
b325eb0da4 | ||
|
71ca5d8049 | ||
|
8716ffd2f1 | ||
|
0cad0920c6 | ||
|
54568adfdd | ||
|
3bf2e6eee5 | ||
|
6d7591625d | ||
|
398e5c2a93 | ||
|
33a5911f94 | ||
|
be7082f5e2 | ||
|
59e369e37d | ||
|
077702b8b2 | ||
|
e192009325 | ||
|
d87ff7bf4d | ||
|
88d5b106cf | ||
|
08c45876df | ||
|
20082441ef | ||
|
dbcd050c66 | ||
|
6ed563e4b4 | ||
|
f61051c463 | ||
|
0eee65bc42 | ||
|
4142601a4b | ||
|
3f5eba1a60 | ||
|
b1c92cf4e8 | ||
|
6282c81bc5 | ||
|
dda68ac044 | ||
|
0199676a6d | ||
|
692348c395 | ||
|
4cd5efbba5 | ||
|
3e76214d07 | ||
|
28abaa7450 | ||
|
297f896552 | ||
|
fe7ddbb5c3 | ||
|
0a87ae6fd4 | ||
|
96d9a77dbe | ||
|
01322572bb | ||
|
e2ce28347a | ||
|
52ef9a84dd | ||
|
aebd70cc25 | ||
|
c23932eb00 | ||
|
cb213f4417 | ||
|
90c29240e0 | ||
|
c62c66edef | ||
|
80bfd9ce02 | ||
|
f559e6a395 | ||
|
2f108a46d0 | ||
|
d5739409e5 | ||
|
9561e952a3 | ||
|
874b37ef35 | ||
|
bab5a5ab5e | ||
|
5d5e5a164f | ||
|
c49f6f8337 | ||
|
3e5e8a900b | ||
|
82f4fef876 | ||
|
eca1e05aee | ||
|
5854549302 | ||
|
b4c59662ac | ||
|
06474b81b2 | ||
|
0c2c87d42c | ||
|
df57349b49 | ||
|
6de761d1c3 | ||
|
3745c80567 | ||
|
7997e40ef6 | ||
|
78b39ebd5a | ||
|
792008ab4e | ||
|
d8c3638ac8 | ||
|
08a439e37e | ||
|
30f71e531a | ||
|
fa54f00a9d | ||
|
460bd4f9aa | ||
|
eb4716ba82 | ||
|
f1217682a9 | ||
|
3534268854 | ||
|
341ea7110a | ||
|
c33bf822cc | ||
|
810dceea88 | ||
|
7c6470fbf9 | ||
|
560bd427d2 | ||
|
31e340e8e2 | ||
|
b445128fb5 | ||
|
8c36287f7c | ||
|
61fc5b656a | ||
|
b1e5a86916 | ||
|
bb226c431e | ||
|
295251192a | ||
|
3b21f385cd | ||
|
ce931ab8a4 | ||
|
c35932e24c | ||
|
751fcc7a5b | ||
|
63bdaa0adf | ||
|
e259be9268 | ||
|
de317a6fe8 | ||
|
566d222bfd | ||
|
61a8113c39 | ||
|
292aa4dec4 | ||
|
d10684f7ea | ||
|
62e82ea9ee | ||
|
bbcdb370f9 | ||
|
a371015be7 | ||
|
0787381e30 | ||
|
c10c08d975 | ||
|
6dc4b8a79a | ||
|
5070a1fe8d | ||
|
0a951e876a | ||
|
b922898129 | ||
|
da44fae98d | ||
|
497e581e5e | ||
|
3ae18a5583 | ||
|
9dd532eb0b | ||
|
35e222482b | ||
|
c81cc4313a | ||
|
24cfd2e7e5 | ||
|
715c7d2724 | ||
|
2766373632 | ||
|
2ee12e5bdf | ||
|
d6544c0c71 | ||
|
720231d33f | ||
|
4d92074505 | ||
|
5e8a7ce21e | ||
|
69734af3ba | ||
|
21eef022b5 | ||
|
407a5b77c3 | ||
|
9795643a34 | ||
|
12e71da73d | ||
|
2601150f03 | ||
|
77bf85342b | ||
|
3578c1c040 | ||
|
792c93694d | ||
|
e124cd37f1 | ||
|
bedaf7891e | ||
|
45969a00b7 | ||
|
9e8cab609d | ||
|
dbc525e8fb | ||
|
689de6c5e2 | ||
|
071ff5b626 | ||
|
f4aa3e0ee8 | ||
|
fd803c21ec | ||
|
61f5950b4f | ||
|
94ef0d856f | ||
|
96bc081ea9 | ||
|
d236735214 | ||
|
3cd1434341 | ||
|
bef419a6ad | ||
|
724b288232 | ||
|
6560a7ad38 | ||
|
f5b019e998 | ||
|
619a66f999 | ||
|
99d7bea977 | ||
|
719585bfda | ||
|
5ccd3365bf | ||
|
f58290cad3 | ||
|
408df377b7 | ||
|
95ed662935 | ||
|
ea32cd2673 | ||
|
c3ee8ec4b2 | ||
|
3469271ec2 | ||
|
379830f7eb | ||
|
506f60bb0f | ||
|
f8abd26030 | ||
|
324ae744d7 | ||
|
bc37cdd57b | ||
|
87e7d0026f | ||
|
5d92267675 | ||
|
6bc6042197 | ||
|
77e3e0878f | ||
|
91ee708c37 | ||
|
89a9ab4534 | ||
|
06d78575cc | ||
|
367ec111e4 | ||
|
e48ef997c0 | ||
|
e1fcc1f21f | ||
|
c3271d7407 | ||
|
a603f99786 | ||
|
9476046868 | ||
|
24426ef322 | ||
|
0faa593658 | ||
|
b24be12405 | ||
|
3432548c1a | ||
|
18f8f2e6d2 | ||
|
0802677d0b | ||
|
06e5a40b41 | ||
|
442e171d06 | ||
|
0acf13445a | ||
|
e119463209 | ||
|
2c0240e16f | ||
|
4ad394f771 | ||
|
456f90cd25 | ||
|
e21abeea37 | ||
|
11e8fad2e9 | ||
|
f92a5da7c2 | ||
|
0ef6da1350 | ||
|
68326716f8 | ||
|
97a17d0849 | ||
|
b11c57d4b5 | ||
|
fa4b73cb52 | ||
|
3d88881f67 | ||
|
e4148d9ba9 | ||
|
d09ee0c2ff | ||
|
513b810631 | ||
|
6dc8d52deb | ||
|
6be8ee1cd7 | ||
|
c0e9676fda | ||
|
858093fe9a | ||
|
ecb5b69101 | ||
|
377f0f2c82 | ||
|
4c4b62cb3a | ||
|
abd569d79a | ||
|
57b562d622 | ||
|
c826081253 | ||
|
5e598f7deb | ||
|
667257a75a | ||
|
eb6b6529cd | ||
|
df11956c3c | ||
|
83411ad127 | ||
|
641d7d8e42 | ||
|
2af5cf496c | ||
|
a209ba77ea | ||
|
1b677c6dc7 | ||
|
8aaac8c431 | ||
|
ad93be12fb | ||
|
d881cd7eb3 | ||
|
e48fa711a3 | ||
|
bd570d167b | ||
|
1c7f7ef7b7 | ||
|
b260ef7ab6 | ||
|
a7e17aee9a | ||
|
429817b8c4 | ||
|
d3d48d1d07 | ||
|
fd296d1a6a | ||
|
7c849abf29 | ||
|
1c32be451c | ||
|
428c045aab | ||
|
a0b5468189 | ||
|
04f3511fb3 | ||
|
10ae1bba59 | ||
|
a3649ca243 | ||
|
bf8fb0c51f | ||
|
39078225f1 | ||
|
bc2b288547 | ||
|
f7a2d2a92d | ||
|
b92027f31e | ||
|
689d7c0cc4 | ||
|
5ba0fba03d | ||
|
d551c82d34 | ||
|
7f48246165 | ||
|
a29a0a0785 | ||
|
ef742e715b | ||
|
118e42884e | ||
|
6289438e62 | ||
|
c566d4d7cf | ||
|
ab13017117 | ||
|
6e67b1902e | ||
|
57bbbc9f7a | ||
|
fe98e57fc4 | ||
|
41ca4e938d | ||
|
5b18172896 | ||
|
c5f2aba9b2 | ||
|
2dacd7d703 | ||
|
e6ed2a2231 | ||
|
dd53e1800e | ||
|
2b3b7dbc79 | ||
|
681351d740 | ||
|
760f1f4d94 | ||
|
1f07f4ab4c | ||
|
f1fae7aac6 | ||
|
937e591430 | ||
|
662ce3b484 | ||
|
a70e327a8e | ||
|
8bd962c006 | ||
|
cb5849d8a1 | ||
|
123ce171d2 | ||
|
a56d8c70d6 | ||
|
7436cb1c86 | ||
|
1b7afe679e | ||
|
14950843cf | ||
|
8b4f7095e2 | ||
|
c71ad05f55 | ||
|
d27164bf20 | ||
|
344994c7f0 | ||
|
4010ed6c23 | ||
|
27df8bd84c | ||
|
59aec11315 | ||
|
a004a978fa | ||
|
89244932c6 | ||
|
a4ab9a0a6c | ||
|
f10a9238dc | ||
|
2310087e03 | ||
|
c7b2004e43 | ||
|
5ba39861d7 | ||
|
87acd73efc | ||
|
deef511362 | ||
|
2b1e56973e | ||
|
20dca0f6b6 | ||
|
b17280522b | ||
|
f83a192bfd | ||
|
7dc8fd4a1e | ||
|
56859d09df | ||
|
f8fe76add2 | ||
|
f9d30bdfad | ||
|
c5a05c15df | ||
|
88dd1aca45 | ||
|
edb033ccd7 | ||
|
9a4b0de1af | ||
|
b37a77f23f | ||
|
bb22908cf7 | ||
|
2a273acd09 | ||
|
3609d36111 | ||
|
95889f358c | ||
|
fa98c6b8c2 | ||
|
03ec48e32c | ||
|
712b25fb6e | ||
|
968ec879f5 | ||
|
8a00a036c4 | ||
|
a71063dd1f | ||
|
32fbfd8d1e | ||
|
a2bea34ac1 | ||
|
616e1be0b4 | ||
|
b05ddb2003 | ||
|
2c1dbe63de | ||
|
343882e4c4 | ||
|
b01ec1d727 | ||
|
f840c85666 | ||
|
cbd2bc8e99 | ||
|
df34954c9e | ||
|
b7857027d5 | ||
|
2d82d1b8ee | ||
|
2f165d595a | ||
|
418970eab2 | ||
|
421c2f5602 | ||
|
e361f14a96 | ||
|
a078ace99c | ||
|
d0f5d684a9 | ||
|
0f58218bad | ||
|
e864becace | ||
|
a8603075d4 | ||
|
6868577e32 | ||
|
d3fa1dd226 | ||
|
65b4c5cec9 | ||
|
c1d4e1944d | ||
|
18c3b59318 | ||
|
693aac283a | ||
|
a522d09734 | ||
|
c807572bdf | ||
|
70564219ae | ||
|
636b7c5475 | ||
|
bf76240724 | ||
|
667266f387 | ||
|
5d541e4ae6 | ||
|
dd3b8c25e5 | ||
|
c223d4e4ec | ||
|
84ecc89f8a | ||
|
b915e7bc37 | ||
|
cda49944f7 | ||
|
9571eb3a15 | ||
|
c1b3f2beb4 | ||
|
b0088b8bd3 | ||
|
9d19f6b9d6 | ||
|
4c042e249b | ||
|
f3975fdefc | ||
|
e4918d29f3 | ||
|
fc3e633d62 | ||
|
67cc668500 | ||
|
4b9549dfbf | ||
|
0456d6e357 | ||
|
ff7ecd270c | ||
|
2c47c8c86b | ||
|
abbfef2aef | ||
|
8da6906e40 | ||
|
9789c55ef9 | ||
|
5d031b3df2 | ||
|
6811b8dc5c | ||
|
e4215917fc | ||
|
3bbb39d7b6 | ||
|
2b850ba781 | ||
|
dfb3454f6e | ||
|
1b44ba3367 | ||
|
e09e541c82 | ||
|
503f891c9e | ||
|
cf8a22f50b | ||
|
ded8262985 | ||
|
e960720298 | ||
|
c8b6ed5823 | ||
|
1b200bcc90 | ||
|
fede5969f9 | ||
|
f34eb9c9e6 | ||
|
8a4e915fe1 | ||
|
217d42983e | ||
|
1885b2120c | ||
|
fcb76a9ebc | ||
|
6c4da7bebe | ||
|
ccc188c113 | ||
|
518f0b0265 | ||
|
9e09755ef0 | ||
|
ac45e4f6c8 | ||
|
9335e2a6c9 | ||
|
f082797d9b | ||
|
b613747153 | ||
|
9de1bef821 | ||
|
ff427e6dcb | ||
|
5257c7c9f4 | ||
|
dd0a234c05 | ||
|
92e9a3b91c | ||
|
d563527289 | ||
|
71aace5569 | ||
|
a683d9f676 | ||
|
700398ba13 | ||
|
6e4a8cac04 | ||
|
5a3a346c59 | ||
|
a8108748fe | ||
|
d8635682bb | ||
|
2d8054be18 | ||
|
80b5dc0068 | ||
|
d568a18e0a | ||
|
dc1d9646a9 | ||
|
df321f27af | ||
|
6735b01775 | ||
|
ae4d330131 | ||
|
5de358d38e | ||
|
6faf7fc994 | ||
|
8b66abfbfc | ||
|
b8e67deb13 | ||
|
8b4d8a76ac | ||
|
021b820736 | ||
|
d94135c9cd | ||
|
e3943cb07e | ||
|
74c9e0400d | ||
|
255d2d4581 | ||
|
872d336ded | ||
|
4005962c5b | ||
|
e0eb295a79 | ||
|
6f2cd3ec08 | ||
|
8801c7741b | ||
|
e739c379ae | ||
|
fb69312642 | ||
|
42450af885 | ||
|
a47a7ccb54 | ||
|
b0b924ee71 | ||
|
80f6ecc617 | ||
|
68cad9a953 | ||
|
e8960c6f2f | ||
|
d5026897c1 | ||
|
37b1978da5 | ||
|
625842fd0d | ||
|
658bec3ecc | ||
|
fc4cd01f67 | ||
|
7ed4a26be6 | ||
|
0dc017704a | ||
|
3131310642 | ||
|
7e581e9d3a | ||
|
1342aad032 | ||
|
675ce2346d | ||
|
224e904306 | ||
|
d3578a957d | ||
|
422ce8aebb | ||
|
0020402685 | ||
|
397e0c4a27 | ||
|
568141b2bc | ||
|
059a5a678a | ||
|
05960d3573 | ||
|
9bf87971e7 | ||
|
53ffefe091 | ||
|
54d7953179 | ||
|
627a14f37e | ||
|
9aa9b15b62 | ||
|
34135cce5d | ||
|
730a64be07 | ||
|
5ef229f02c | ||
|
70fca8ce5d | ||
|
381e3129a3 | ||
|
dcd78a1cfa | ||
|
a25f7e4f99 | ||
|
3d83775468 | ||
|
00e61d9a80 | ||
|
48896474e6 | ||
|
6968839f21 | ||
|
418e441dfc | ||
|
f2279859b3 | ||
|
17f4fe254a | ||
|
642d93c061 | ||
|
d178c28317 | ||
|
ae32f978f6 | ||
|
8d2ad02208 | ||
|
000bbad21e | ||
|
b5c9de775d | ||
|
bfd1628d5b | ||
|
1ec6c4506a | ||
|
d58064587d | ||
|
cebea64d36 | ||
|
b0080159d9 | ||
|
a63ae08f5d | ||
|
28d17b04b1 | ||
|
ae336ae494 | ||
|
ed1fe4b938 | ||
|
bc2e5e7a37 | ||
|
273ece96b5 | ||
|
8a82a71ded | ||
|
87ce22e031 | ||
|
5cecb10b00 | ||
|
0188ffd19f | ||
|
288059eecd | ||
|
38bf8d6a6c | ||
|
9c9ca9123a | ||
|
44d216100b | ||
|
f4ef375835 | ||
|
b2fa4608a2 | ||
|
ef9b2af018 | ||
|
c1204f6615 | ||
|
b6688baef1 | ||
|
e56fcc48e1 | ||
|
73f2c89d13 | ||
|
f00d6863cf | ||
|
3d2aeb890b | ||
|
1a827a4dd4 | ||
|
285f08fc3b | ||
|
e625520bc8 | ||
|
f75b3e6cda | ||
|
5a4859f05c | ||
|
42ebf24ad4 | ||
|
0046d32f1c | ||
|
45237888e3 | ||
|
3c8507daee | ||
|
fe09511aed | ||
|
27fd709316 | ||
|
0a70257b4c | ||
|
ecaf8750dd | ||
|
2fb203e1a1 | ||
|
14003b9805 | ||
|
1904978856 | ||
|
f3e45410d5 | ||
|
c8c2fd23b4 | ||
|
c10283d349 | ||
|
f5061aa7ff | ||
|
120eaa534e | ||
|
87f49874c6 | ||
|
09470bef96 | ||
|
4e9c6b2f91 | ||
|
cef80c7533 | ||
|
4cdeeb4a36 | ||
|
0898c63ca3 | ||
|
242a766794 | ||
|
8b2b5c03ba | ||
|
f20682cc6f | ||
|
24cd9158d4 | ||
|
e4e6209835 | ||
|
33b51c40dd | ||
|
222d44bd85 | ||
|
0352ad2d63 | ||
|
c009637e09 | ||
|
02262e5ad9 | ||
|
ba10cb6825 | ||
|
1d299721e3 | ||
|
89fba64372 | ||
|
2e9b4b4e5e | ||
|
bb97b2a1ef | ||
|
2589c5fac8 | ||
|
54704e1e6a | ||
|
574f224767 | ||
|
a556d8520b | ||
|
3c8450fd2f | ||
|
81f9119da6 | ||
|
ce1aa6137b | ||
|
4e8659e156 | ||
|
76d8aa5377 | ||
|
b88f213e6a | ||
|
621518e84a | ||
|
f68cfd8de2 | ||
|
366d57b2b3 | ||
|
b6358d1036 | ||
|
8b07bc15f0 | ||
|
20f848bcec | ||
|
f875c1da27 | ||
|
a60e1102c4 | ||
|
035691ed01 | ||
|
9e012f6e50 | ||
|
59087c77e1 | ||
|
5749cdd16c | ||
|
9b18c33dd8 | ||
|
37e97a782c | ||
|
eecffb5116 | ||
|
edc16ec434 | ||
|
56996e2138 | ||
|
1ec70660c6 | ||
|
2fe9e519b4 | ||
|
00fdc6281c | ||
|
8bb1b2b94f | ||
|
f7101f7839 | ||
|
6e8cc24e64 | ||
|
9361943e47 | ||
|
ef19b4f85f | ||
|
9a84ef06ad | ||
|
6537fa17e1 | ||
|
5a3780aef9 | ||
|
7c6a290ea9 | ||
|
e30e28712f | ||
|
009e46f7f2 | ||
|
2c70065e36 | ||
|
51a91d94e5 | ||
|
9af5ab43af | ||
|
5ab432856d | ||
|
efcd77078e | ||
|
fcf64ffa5e | ||
|
908145ceed | ||
|
50c19f4763 | ||
|
ac7cc458be | ||
|
d091796418 | ||
|
27a2394115 | ||
|
35c0394c5b | ||
|
36cd31d69d | ||
|
04af6de363 | ||
|
b559b73be4 | ||
|
14031afb62 | ||
|
4d9a62339d | ||
|
cc61ed4a07 | ||
|
1947edb69a | ||
|
a7f224b1af | ||
|
b15115565c | ||
|
9cd9ebd060 | ||
|
002782569d | ||
|
b55374c75a | ||
|
3ec3b88456 | ||
|
fbdad00cdb | ||
|
f9ab13a145 | ||
|
d4ae8194eb | ||
|
c6e959eb45 | ||
|
a71be3827d | ||
|
5045c50b45 | ||
|
3b0de2c7a6 | ||
|
c623797c1f | ||
|
861d775dd7 | ||
|
be42a35eca | ||
|
d96228f9ee | ||
|
ba4c927c01 | ||
|
c6e8b341f3 | ||
|
d881c98224 | ||
|
57fd18cd7c | ||
|
764daa8a36 | ||
|
fc901e8c65 | ||
|
da14c7f24c | ||
|
956fd47ed6 | ||
|
0d6a8d90c5 | ||
|
4abeadc636 | ||
|
84cc6e092a | ||
|
c96ab05d7d | ||
|
d8eeb70707 | ||
|
29710b7cc1 | ||
|
4202cfb88f | ||
|
92cbbefcf4 | ||
|
d2285b6913 | ||
|
c296e431db | ||
|
4ca7307eea | ||
|
85e6beaf44 | ||
|
340a23a961 | ||
|
1a746f2882 | ||
|
e9e4e8d44a | ||
|
b7374e934c | ||
|
1f48ec21cd | ||
|
5c488cd03b | ||
|
08af41b1dd | ||
|
76a75bf3d0 | ||
|
60b8934a4b | ||
|
83a733984b | ||
|
89c6224062 | ||
|
e4894a45a4 | ||
|
d9ebdf6fa7 | ||
|
5fd374191b | ||
|
21c0eb821f | ||
|
817fc86c3c | ||
|
ba6d84cdc8 | ||
|
8885c2457a | ||
|
92191c4ed2 | ||
|
cf5cc1a6ca | ||
|
fede660d21 | ||
|
805fa42a2c | ||
|
1b6f0137b9 | ||
|
6ecd801c23 | ||
|
ca5139929b | ||
|
d072017bdc | ||
|
c785f5b625 | ||
|
2d2b833802 | ||
|
6ac7ce8f15 | ||
|
b9e4682d3f | ||
|
3a502b36a8 | ||
|
cb2c2b8141 | ||
|
c85b3136fb | ||
|
79b345fe1a | ||
|
b080914eff | ||
|
c370d49ddb | ||
|
2e778e342a | ||
|
407ce63630 | ||
|
30e0c5ac73 | ||
|
272e8f034f | ||
|
bf7ab3fe2b | ||
|
2ab7910aa7 | ||
|
ab45f1a13f | ||
|
e3cafdc408 | ||
|
e319117805 | ||
|
6f0754cf9d | ||
|
d80034997a | ||
|
71eb7bd627 | ||
|
86fac1285a | ||
|
2bfe83b4a8 | ||
|
ea4c06e927 | ||
|
b5a005719f | ||
|
502dbf3474 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -27,6 +27,4 @@ hs_err_pid*
|
||||
/target/
|
||||
|
||||
/src/main/resources/static/
|
||||
/web_src/node_modules/
|
||||
/web_src/build/
|
||||
certificates
|
||||
|
56
app.sh
56
app.sh
@ -1,56 +0,0 @@
|
||||
#!/bin/bash
|
||||
cd $(dirname $0)
|
||||
exe="java -jar wvp-pro-2.6.9.jar"
|
||||
arg=""
|
||||
|
||||
status(){
|
||||
count=$(ps aux|grep "$exe"|grep -v grep|wc -l)
|
||||
if [ $count -eq 0 ] ; then
|
||||
echo "$exe is stopped"
|
||||
return
|
||||
fi
|
||||
echo "$exe is running"
|
||||
}
|
||||
|
||||
|
||||
start(){
|
||||
count=$(ps aux|grep "$exe"|grep -v grep|wc -l)
|
||||
if [ $count -eq 0 ] ; then
|
||||
echo "staring $exe"
|
||||
nohup $exe $arg > nohup.out 2>&1 &
|
||||
sleep 1
|
||||
status
|
||||
exit 0
|
||||
fi
|
||||
status
|
||||
}
|
||||
|
||||
stop(){
|
||||
echo "kill process"
|
||||
nohup pkill -f "$exe" >/dev/null 2>&1 &
|
||||
sleep 1
|
||||
status
|
||||
}
|
||||
|
||||
restart(){
|
||||
stop
|
||||
sleep 5
|
||||
start
|
||||
}
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
status)
|
||||
status;;
|
||||
*)
|
||||
echo "use $0 start|stop|restart|status"
|
||||
esac
|
||||
|
@ -153,7 +153,7 @@ user-settings:
|
||||
# 国标是否录制
|
||||
record-sip: true
|
||||
# 是否将日志存储进数据库
|
||||
logInDatebase: true
|
||||
logInDatabase: true
|
||||
# 第三方匹配,用于从stream钟获取有效信息
|
||||
thirdPartyGBIdReg: [\s\S]*
|
||||
```
|
||||
|
BIN
libs/jdbc-x86/bcprov-jdk15on-1.70.jar
Normal file
BIN
libs/jdbc-x86/bcprov-jdk15on-1.70.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre6.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre6.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre7.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre7.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jre6.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jre6.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jre7.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jre7.jar
Normal file
Binary file not shown.
655
pom.xml
655
pom.xml
@ -1,148 +1,155 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.2</version>
|
||||
</parent>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.17</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.genersoft</groupId>
|
||||
<artifactId>wvp-pro</artifactId>
|
||||
<version>2.6.9</version>
|
||||
<name>web video platform</name>
|
||||
<description>国标28181视频平台</description>
|
||||
<packaging>${project.packaging}</packaging>
|
||||
<groupId>com.genersoft</groupId>
|
||||
<artifactId>wvp-pro</artifactId>
|
||||
<version>2.7.0</version>
|
||||
<name>web video platform</name>
|
||||
<description>国标28181视频平台</description>
|
||||
<packaging>${project.packaging}</packaging>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>nexus-aliyun</id>
|
||||
<name>Nexus aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<layout>default</layout>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>nexus-aliyun</id>
|
||||
<name>Nexus aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>nexus-aliyun</id>
|
||||
<name>Nexus aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<layout>default</layout>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>nexus-aliyun</id>
|
||||
<name>Nexus aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<!-- 依赖版本 -->
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
||||
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
|
||||
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
|
||||
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
|
||||
<!-- 依赖版本 -->
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
||||
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
|
||||
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
|
||||
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
|
||||
<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
|
||||
<springboot.version>2.7.2</springboot.version>
|
||||
</properties>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jar</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<project.packaging>jar</project.packaging>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>war</id>
|
||||
<properties>
|
||||
<project.packaging>war</project.packaging>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jar</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<project.packaging>jar</project.packaging>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>war</id>
|
||||
<properties>
|
||||
<project.packaging>war</project.packaging>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
<version>5.8.24</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mysql数据库 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--postgresql-->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.5.1</version>
|
||||
</dependency>
|
||||
<!-- mysql数据库 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--postgresql-->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- kingbase人大金仓 -->
|
||||
<!-- https://mvnrepository.com/artifact/cn.com.kingbase/kingbase8 -->
|
||||
@ -152,13 +159,33 @@
|
||||
<version>8.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--Mybatis分页插件 -->
|
||||
<!--Mybatis分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.6</version>
|
||||
</dependency>
|
||||
|
||||
<!--在线文档 -->
|
||||
<!--在线文档 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>1.6.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-security</artifactId>
|
||||
<version>1.6.10</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--在线文档 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
@ -166,132 +193,155 @@
|
||||
<version>1.6.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<!--参数校验 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<!--参数校验 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<!-- 日志相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sip协议栈 -->
|
||||
<dependency>
|
||||
<groupId>javax.sip</groupId>
|
||||
<artifactId>jain-sip-ri</artifactId>
|
||||
<version>1.3.0-91</version>
|
||||
</dependency>
|
||||
<!-- sip协议栈 -->
|
||||
<dependency>
|
||||
<groupId>javax.sip</groupId>
|
||||
<artifactId>jain-sip-ri</artifactId>
|
||||
<version>1.3.0-91</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 取代log4j -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>1.7.36</version>
|
||||
</dependency>
|
||||
<!-- 取代log4j -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>1.7.36</version>
|
||||
</dependency>
|
||||
|
||||
<!-- xml解析库 -->
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
<!-- xml解析库 -->
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- json解析库fastjson2 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-extension</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
<!-- json解析库fastjson2 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-extension</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
<!-- okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp 调试日志 -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
<!-- okhttp 调试日志 -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp-digest -->
|
||||
<dependency>
|
||||
<groupId>io.github.rburgst</groupId>
|
||||
<artifactId>okhttp-digest</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
<!-- okhttp-digest -->
|
||||
<dependency>
|
||||
<groupId>io.github.rburgst</groupId>
|
||||
<artifactId>okhttp-digest</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>net.sf.kxml</groupId>-->
|
||||
<!-- <artifactId>kxml2</artifactId>-->
|
||||
<!-- <version>2.3.0</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>net.sf.kxml</groupId>-->
|
||||
<!-- <artifactId>kxml2</artifactId>-->
|
||||
<!-- <version>2.3.0</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- jwt实现 -->
|
||||
<dependency>
|
||||
<groupId>org.bitbucket.b_c</groupId>
|
||||
<artifactId>jose4j</artifactId>
|
||||
<version>0.9.3</version>
|
||||
</dependency>
|
||||
<!-- jwt实现 -->
|
||||
<dependency>
|
||||
<groupId>org.bitbucket.b_c</groupId>
|
||||
<artifactId>jose4j</artifactId>
|
||||
<version>0.9.3</version>
|
||||
</dependency>
|
||||
|
||||
<!--反向代理-->
|
||||
<dependency>
|
||||
<groupId>org.mitre.dsmiley.httpproxy</groupId>
|
||||
<artifactId>smiley-http-proxy-servlet</artifactId>
|
||||
<version>1.12.1</version>
|
||||
</dependency>
|
||||
<!--反向代理-->
|
||||
<dependency>
|
||||
<groupId>org.mitre.dsmiley.httpproxy</groupId>
|
||||
<artifactId>smiley-http-proxy-servlet</artifactId>
|
||||
<version>1.12.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--excel解析库-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
<!--excel解析库-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.24.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.2.2</version>
|
||||
</dependency>
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <!– 检测文件编码 –>-->
|
||||
<!-- <!– https://mvnrepository.com/artifact/cpdetector/cpdetector –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cpdetector</groupId>-->
|
||||
<!-- <artifactId>cpdetector</artifactId>-->
|
||||
<!-- <version>1.0.8</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- 检测文件编码 -->
|
||||
<!-- https://mvnrepository.com/artifact/cpdetector/cpdetector -->
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>cpdetector</groupId>-->
|
||||
<!-- <artifactId>cpdetector</artifactId>-->
|
||||
<!-- <version>1.0.8</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.3-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.rholder</groupId>
|
||||
<artifactId>guava-retrying</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
@ -299,31 +349,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--<!– 开发工具 –>-->
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-devtools</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--MapStruct-->
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>${org.mapstruct.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${org.mapstruct.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@ -339,73 +369,46 @@
|
||||
<includeSystemScope>true</includeSystemScope>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<offline>true</offline>
|
||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||
<dateFormat>yyyyMMdd</dateFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${org.mapstruct.version}</version>
|
||||
</path>
|
||||
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</path>
|
||||
|
||||
<path>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</path>
|
||||
<!-- other annotation processors -->
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<offline>true</offline>
|
||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||
<dateFormat>yyyyMMdd</dateFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
||||
|
@ -1,2 +0,0 @@
|
||||
alter table wvp_device_channel
|
||||
change stream_id stream_id varying(255)
|
@ -1,63 +1,63 @@
|
||||
package com.genersoft.iot.vmp;
|
||||
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 启动类
|
||||
*/
|
||||
@ServletComponentScan("com.genersoft.iot.vmp.conf")
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
public class VManageBootstrap extends SpringBootServletInitializer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class);
|
||||
|
||||
private static String[] args;
|
||||
private static ConfigurableApplicationContext context;
|
||||
public static void main(String[] args) {
|
||||
VManageBootstrap.args = args;
|
||||
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
|
||||
GitUtil gitUtil1 = SpringBeanFactory.getBean("gitUtil");
|
||||
logger.info("构建版本: {}", gitUtil1.getBuildVersion());
|
||||
logger.info("构建时间: {}", gitUtil1.getBuildDate());
|
||||
logger.info("GIT最后提交时间: {}", gitUtil1.getCommitTime());
|
||||
}
|
||||
// 项目重启
|
||||
public static void restart() {
|
||||
context.close();
|
||||
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(VManageBootstrap.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
super.onStartup(servletContext);
|
||||
|
||||
servletContext.setSessionTrackingModes(
|
||||
Collections.singleton(SessionTrackingMode.COOKIE)
|
||||
);
|
||||
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
|
||||
sessionCookieConfig.setHttpOnly(true);
|
||||
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp;
|
||||
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 启动类
|
||||
*/
|
||||
@ServletComponentScan("com.genersoft.iot.vmp.conf")
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
public class VManageBootstrap extends SpringBootServletInitializer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class);
|
||||
|
||||
private static String[] args;
|
||||
private static ConfigurableApplicationContext context;
|
||||
public static void main(String[] args) {
|
||||
VManageBootstrap.args = args;
|
||||
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
|
||||
GitUtil gitUtil1 = SpringBeanFactory.getBean("gitUtil");
|
||||
logger.info("构建版本: {}", gitUtil1.getBuildVersion());
|
||||
logger.info("构建时间: {}", gitUtil1.getBuildDate());
|
||||
logger.info("GIT最后提交时间: {}", gitUtil1.getCommitTime());
|
||||
}
|
||||
// 项目重启
|
||||
public static void restart() {
|
||||
context.close();
|
||||
VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(VManageBootstrap.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
super.onStartup(servletContext);
|
||||
|
||||
servletContext.setSessionTrackingModes(
|
||||
Collections.singleton(SessionTrackingMode.COOKIE)
|
||||
);
|
||||
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
|
||||
sessionCookieConfig.setHttpOnly(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -76,6 +77,8 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
private String endTime;
|
||||
@Schema(description = "进度(录像下载使用)")
|
||||
private double progress;
|
||||
@Schema(description = "文件下载地址(录像下载使用)")
|
||||
private DownloadFileInfo downLoadFilePath;
|
||||
|
||||
@Schema(description = "是否暂停(录像回放使用)")
|
||||
private boolean pause;
|
||||
@ -523,6 +526,69 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
StreamInfo instance = null;
|
||||
try{
|
||||
instance = (StreamInfo)super.clone();
|
||||
if (this.flv != null) {
|
||||
instance.flv=this.flv.clone();
|
||||
}
|
||||
if (this.ws_flv != null ){
|
||||
instance.ws_flv= this.ws_flv.clone();
|
||||
}
|
||||
if (this.hls != null ) {
|
||||
instance.hls= this.hls.clone();
|
||||
}
|
||||
if (this.ws_hls != null ) {
|
||||
instance.ws_hls= this.ws_hls.clone();
|
||||
}
|
||||
if (this.ts != null ) {
|
||||
instance.ts= this.ts.clone();
|
||||
}
|
||||
if (this.ws_ts != null ) {
|
||||
instance.ws_ts= this.ws_ts.clone();
|
||||
}
|
||||
if (this.fmp4 != null ) {
|
||||
instance.fmp4= this.fmp4.clone();
|
||||
}
|
||||
if (this.ws_fmp4 != null ) {
|
||||
instance.ws_fmp4= this.ws_fmp4.clone();
|
||||
}
|
||||
if (this.rtc != null ) {
|
||||
instance.rtc= this.rtc.clone();
|
||||
}
|
||||
if (this.https_flv != null) {
|
||||
instance.https_flv= this.https_flv.clone();
|
||||
}
|
||||
if (this.wss_flv != null) {
|
||||
instance.wss_flv= this.wss_flv.clone();
|
||||
}
|
||||
if (this.https_hls != null) {
|
||||
instance.https_hls= this.https_hls.clone();
|
||||
}
|
||||
if (this.wss_hls != null) {
|
||||
instance.wss_hls= this.wss_hls.clone();
|
||||
}
|
||||
if (this.wss_ts != null) {
|
||||
instance.wss_ts= this.wss_ts.clone();
|
||||
}
|
||||
if (this.https_fmp4 != null) {
|
||||
instance.https_fmp4= this.https_fmp4.clone();
|
||||
}
|
||||
if (this.wss_fmp4 != null) {
|
||||
instance.wss_fmp4= this.wss_fmp4.clone();
|
||||
}
|
||||
if (this.rtcs != null) {
|
||||
instance.rtcs= this.rtcs.clone();
|
||||
}
|
||||
if (this.rtsp != null) {
|
||||
instance.rtsp= this.rtsp.clone();
|
||||
}
|
||||
if (this.rtsps != null) {
|
||||
instance.rtsps= this.rtsps.clone();
|
||||
}
|
||||
if (this.rtmp != null) {
|
||||
instance.rtmp= this.rtmp.clone();
|
||||
}
|
||||
if (this.rtmps != null) {
|
||||
instance.rtmps= this.rtmps.clone();
|
||||
}
|
||||
}catch(CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -542,5 +608,11 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
this.subStream = subStream;
|
||||
}
|
||||
|
||||
public DownloadFileInfo getDownLoadFilePath() {
|
||||
return downLoadFilePath;
|
||||
}
|
||||
|
||||
public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
|
||||
this.downLoadFilePath = downLoadFilePath;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import java.io.Serializable;
|
||||
|
||||
|
||||
@Schema(description = "流地址信息")
|
||||
public class StreamURL implements Serializable {
|
||||
public class StreamURL implements Serializable,Cloneable {
|
||||
|
||||
@Schema(description = "协议")
|
||||
private String protocol;
|
||||
@ -77,4 +77,8 @@ public class StreamURL implements Serializable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public StreamURL clone() throws CloneNotSupportedException {
|
||||
return (StreamURL) super.clone();
|
||||
}
|
||||
}
|
||||
|
@ -1,176 +1,177 @@
|
||||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
/**
|
||||
* @description: 定义常量
|
||||
* @author: swwheihei
|
||||
* @date: 2019年5月30日 下午3:04:04
|
||||
*
|
||||
*/
|
||||
public class VideoManagerConstants {
|
||||
|
||||
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
|
||||
|
||||
public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
|
||||
|
||||
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
||||
|
||||
public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
|
||||
|
||||
public static final String DEVICE_PREFIX = "VMP_DEVICE_";
|
||||
|
||||
// 设备同步完成
|
||||
public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_";
|
||||
|
||||
public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_";
|
||||
|
||||
public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
|
||||
|
||||
// TODO 此处多了一个_,暂不修改
|
||||
public static final String INVITE_PREFIX = "VMP_INVITE";
|
||||
public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_";
|
||||
public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_";
|
||||
public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_";
|
||||
|
||||
public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_";
|
||||
|
||||
public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_";
|
||||
|
||||
public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_";
|
||||
|
||||
public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_";
|
||||
|
||||
public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_";
|
||||
|
||||
public static final String EVENT_ONLINE_REGISTER = "1";
|
||||
|
||||
public static final String EVENT_ONLINE_MESSAGE = "3";
|
||||
|
||||
public static final String EVENT_OUTLINE_UNREGISTER = "1";
|
||||
|
||||
public static final String EVENT_OUTLINE_TIMEOUT = "2";
|
||||
|
||||
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_MEDIA_USED_SSRC_";
|
||||
|
||||
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
|
||||
|
||||
public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_";
|
||||
|
||||
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
|
||||
|
||||
public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
|
||||
|
||||
public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_";
|
||||
|
||||
public static final String SYSTEM_INFO_CPU_PREFIX = "VMP_SYSTEM_INFO_CPU_";
|
||||
|
||||
public static final String SYSTEM_INFO_MEM_PREFIX = "VMP_SYSTEM_INFO_MEM_";
|
||||
|
||||
public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
|
||||
|
||||
public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_";
|
||||
|
||||
public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";
|
||||
|
||||
|
||||
|
||||
|
||||
//************************** redis 消息*********************************
|
||||
|
||||
/**
|
||||
* 流变化的通知
|
||||
*/
|
||||
public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_GPS = "VM_MSG_GPS";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
|
||||
/**
|
||||
* 接收推流设备列表更新变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* redis 消息通知设备推流到平台
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台开始观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_START_PLAY_NOTIFY = "VM_MSG_STREAM_START_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台停止观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_STOP_PLAY_NOTIFY = "VM_MSG_STREAM_STOP_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息接收关闭一个推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE_REQUESTED = "VM_MSG_STREAM_PUSH_CLOSE_REQUESTED";
|
||||
|
||||
|
||||
/**
|
||||
* redis 消息通知平台通知设备推流结果
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE";
|
||||
|
||||
/**
|
||||
* redis 通知平台关闭推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE";
|
||||
|
||||
/**
|
||||
* redis 消息请求所有的在线通道
|
||||
*/
|
||||
public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
|
||||
|
||||
/**
|
||||
* 移动位置订阅通知
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
|
||||
|
||||
/**
|
||||
* 报警订阅的通知(收到报警向redis发出通知)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
|
||||
|
||||
|
||||
/**
|
||||
* 报警通知的发送 (收到redis发出的通知,转发给其他平台)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive";
|
||||
|
||||
/**
|
||||
* 设备状态订阅的通知
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
|
||||
|
||||
|
||||
//************************** 第三方 ****************************************
|
||||
|
||||
public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
|
||||
public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
|
||||
public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_";
|
||||
public static final String WVP_OTHER_SEND_PS_INFO = "VMP_OTHER_SEND_PS_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_PS_INFO = "VMP_OTHER_RECEIVE_PS_INFO_";
|
||||
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_PRE = "GB_RECORD_INFO_RES_";
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:";
|
||||
|
||||
}
|
||||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
/**
|
||||
* @description: 定义常量
|
||||
* @author: swwheihei
|
||||
* @date: 2019年5月30日 下午3:04:04
|
||||
*
|
||||
*/
|
||||
public class VideoManagerConstants {
|
||||
|
||||
public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_";
|
||||
|
||||
public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
|
||||
|
||||
public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
|
||||
|
||||
public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
|
||||
|
||||
public static final String DEVICE_PREFIX = "VMP_DEVICE_";
|
||||
|
||||
// 设备同步完成
|
||||
public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_";
|
||||
|
||||
public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_";
|
||||
|
||||
public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
|
||||
|
||||
// TODO 此处多了一个_,暂不修改
|
||||
public static final String INVITE_PREFIX = "VMP_INVITE";
|
||||
public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_";
|
||||
public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_";
|
||||
public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_";
|
||||
|
||||
public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_";
|
||||
|
||||
public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_";
|
||||
|
||||
public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_";
|
||||
|
||||
public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_";
|
||||
|
||||
public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_";
|
||||
|
||||
public static final String EVENT_ONLINE_REGISTER = "1";
|
||||
|
||||
public static final String EVENT_ONLINE_MESSAGE = "3";
|
||||
|
||||
public static final String EVENT_OUTLINE_UNREGISTER = "1";
|
||||
|
||||
public static final String EVENT_OUTLINE_TIMEOUT = "2";
|
||||
|
||||
public static final String MEDIA_SSRC_USED_PREFIX = "VMP_MEDIA_USED_SSRC_";
|
||||
|
||||
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
|
||||
|
||||
public static final String MEDIA_STREAM_AUTHORITY = "VMP_MEDIA_STREAM_AUTHORITY_";
|
||||
|
||||
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
|
||||
|
||||
public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
|
||||
|
||||
public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_";
|
||||
|
||||
public static final String SYSTEM_INFO_CPU_PREFIX = "VMP_SYSTEM_INFO_CPU_";
|
||||
|
||||
public static final String SYSTEM_INFO_MEM_PREFIX = "VMP_SYSTEM_INFO_MEM_";
|
||||
|
||||
public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
|
||||
|
||||
public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_";
|
||||
|
||||
public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";
|
||||
public static final String PUSH_STREAM_LIST = "VMP_PUSH_STREAM_LIST_";
|
||||
|
||||
|
||||
|
||||
|
||||
//************************** redis 消息*********************************
|
||||
|
||||
/**
|
||||
* 流变化的通知
|
||||
*/
|
||||
public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_GPS = "VM_MSG_GPS";
|
||||
|
||||
/**
|
||||
* 接收推流设备的GPS变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
|
||||
/**
|
||||
* 接收推流设备列表更新变化通知
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* redis 消息通知设备推流到平台
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台开始观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_START_PLAY_NOTIFY = "VM_MSG_STREAM_START_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息通知上级平台停止观看流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_STOP_PLAY_NOTIFY = "VM_MSG_STREAM_STOP_PLAY_NOTIFY";
|
||||
|
||||
/**
|
||||
* redis 消息接收关闭一个推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE_REQUESTED = "VM_MSG_STREAM_PUSH_CLOSE_REQUESTED";
|
||||
|
||||
|
||||
/**
|
||||
* redis 消息通知平台通知设备推流结果
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE";
|
||||
|
||||
/**
|
||||
* redis 通知平台关闭推流
|
||||
*/
|
||||
public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE";
|
||||
|
||||
/**
|
||||
* redis 消息请求所有的在线通道
|
||||
*/
|
||||
public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
|
||||
|
||||
/**
|
||||
* 移动位置订阅通知
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
|
||||
|
||||
/**
|
||||
* 报警订阅的通知(收到报警向redis发出通知)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
|
||||
|
||||
|
||||
/**
|
||||
* 报警通知的发送 (收到redis发出的通知,转发给其他平台)
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive";
|
||||
|
||||
/**
|
||||
* 设备状态订阅的通知
|
||||
*/
|
||||
public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
|
||||
|
||||
|
||||
//************************** 第三方 ****************************************
|
||||
|
||||
public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
|
||||
public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
|
||||
public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_";
|
||||
public static final String WVP_OTHER_SEND_PS_INFO = "VMP_OTHER_SEND_PS_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_";
|
||||
public static final String WVP_OTHER_RECEIVE_PS_INFO = "VMP_OTHER_RECEIVE_PS_INFO_";
|
||||
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_PRE = "GB_RECORD_INFO_RES_";
|
||||
/**
|
||||
* Redis Const
|
||||
* 设备录像信息结果前缀
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:";
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
|
||||
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
|
||||
if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) {
|
||||
if (uriName != null && userSetting != null && userSetting.getLogInDatabase() != null && userSetting.getLogInDatabase()) {
|
||||
|
||||
LogDto logDto = new LogDto();
|
||||
logDto.setName(uriName);
|
||||
|
@ -12,7 +12,10 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -0,0 +1,83 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.vmanager.cloudRecord.CloudRecordController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 录像文件定时删除
|
||||
*/
|
||||
@Component
|
||||
public class CloudRecordTimer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(CloudRecordTimer.class);
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
/**
|
||||
* 定时查询待删除的录像文件
|
||||
*/
|
||||
// @Scheduled(fixedRate = 10000) //每五秒执行一次,方便测试
|
||||
@Scheduled(cron = "0 0 0 * * ?") //每天的0点执行
|
||||
public void execute(){
|
||||
logger.info("[录像文件定时清理] 开始清理过期录像文件");
|
||||
// 获取配置了assist的流媒体节点
|
||||
List<MediaServerItem> mediaServerItemList = mediaServerService.getAllOnline();
|
||||
if (mediaServerItemList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long result = 0;
|
||||
for (MediaServerItem mediaServerItem : mediaServerItemList) {
|
||||
|
||||
Calendar lastCalendar = Calendar.getInstance();
|
||||
if (mediaServerItem.getRecordDay() > 0) {
|
||||
lastCalendar.setTime(new Date());
|
||||
// 获取保存的最后截至日[期,因为每个节点都有一个日期,也就是支持每个节点设置不同的保存日期,
|
||||
lastCalendar.add(Calendar.DAY_OF_MONTH, -mediaServerItem.getRecordDay());
|
||||
Long lastDate = lastCalendar.getTimeInMillis();
|
||||
|
||||
// 获取到截至日期之前的录像文件列表,文件列表满足未被收藏和保持的。这两个字段目前共能一致,
|
||||
// 为我自己业务系统相关的代码,大家使用的时候直接使用收藏(collect)这一个类型即可
|
||||
List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.queryRecordListForDelete(lastDate, mediaServerItem.getId());
|
||||
if (cloudRecordItemList.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// TODO 后续可以删除空了的过期日期文件夹
|
||||
for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
|
||||
String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName();
|
||||
JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
|
||||
cloudRecordItem.getStream(), date, cloudRecordItem.getFileName());
|
||||
if (jsonObject.getInteger("code") != 0) {
|
||||
logger.warn("[录像文件定时清理] 删除磁盘文件错误: {}:{}", cloudRecordItem.getFilePath(), jsonObject);
|
||||
}
|
||||
}
|
||||
result += cloudRecordServiceMapper.deleteList(cloudRecordItemList);
|
||||
}
|
||||
}
|
||||
logger.info("[录像文件定时清理] 共清理{}个过期录像文件", result);
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -21,8 +20,10 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DynamicTask {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DynamicTask.class);
|
||||
|
||||
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
|
||||
@ -51,9 +52,9 @@ public class DynamicTask {
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
logger.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -62,9 +63,9 @@ public class DynamicTask {
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
logger.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
logger.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,12 +85,12 @@ public class DynamicTask {
|
||||
// 获取执行的时刻
|
||||
Instant startInstant = Instant.now().plusMillis(TimeUnit.MILLISECONDS.toMillis(delay));
|
||||
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
ScheduledFuture future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
logger.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -98,9 +99,9 @@ public class DynamicTask {
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
logger.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
logger.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +111,7 @@ public class DynamicTask {
|
||||
}
|
||||
boolean result = false;
|
||||
if (!ObjectUtils.isEmpty(futureMap.get(key)) && !futureMap.get(key).isCancelled() && !futureMap.get(key).isDone()) {
|
||||
result = futureMap.get(key).cancel(true);
|
||||
result = futureMap.get(key).cancel(false);
|
||||
futureMap.remove(key);
|
||||
runnableMap.remove(key);
|
||||
}
|
||||
@ -142,7 +143,8 @@ public class DynamicTask {
|
||||
public void execute(){
|
||||
if (futureMap.size() > 0) {
|
||||
for (String key : futureMap.keySet()) {
|
||||
if (futureMap.get(key).isDone() || futureMap.get(key).isCancelled()) {
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future.isDone() || future.isCancelled()) {
|
||||
futureMap.remove(key);
|
||||
runnableMap.remove(key);
|
||||
}
|
||||
|
@ -86,6 +86,12 @@ public class MediaConfig{
|
||||
@Value("${media.record-assist-port:0}")
|
||||
private Integer recordAssistPort = 0;
|
||||
|
||||
@Value("${media.record-day:7}")
|
||||
private Integer recordDay;
|
||||
|
||||
@Value("${media.record-path:}")
|
||||
private String recordPath;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@ -218,13 +224,32 @@ public class MediaConfig{
|
||||
mediaServerItem.setRecordAssistIp(recordAssistIp);
|
||||
mediaServerItem.setRecordAssistPort(recordAssistPort);
|
||||
mediaServerItem.setHookAliveInterval(30.00f);
|
||||
|
||||
mediaServerItem.setRecordDay(recordDay);
|
||||
if (recordPath != null) {
|
||||
mediaServerItem.setRecordPath(recordPath);
|
||||
}
|
||||
mediaServerItem.setCreateTime(DateUtil.getNow());
|
||||
mediaServerItem.setUpdateTime(DateUtil.getNow());
|
||||
|
||||
return mediaServerItem;
|
||||
}
|
||||
|
||||
public Integer getRecordDay() {
|
||||
return recordDay;
|
||||
}
|
||||
|
||||
public void setRecordDay(Integer recordDay) {
|
||||
this.recordDay = recordDay;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
|
||||
public String getRtpSendPortRange() {
|
||||
return rtpSendPortRange;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
|
||||
@ -64,6 +65,18 @@ public class ProxyServletConfig {
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
|
||||
HttpRequest proxyRequest) throws IOException {
|
||||
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
|
||||
response.removeHeaders("Access-Control-Allow-Origin");
|
||||
response.setHeader("Access-Control-Allow-Credentials","true");
|
||||
response.removeHeaders("Access-Control-Allow-Credentials");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*/
|
||||
@ -181,6 +194,18 @@ public class ProxyServletConfig {
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
|
||||
HttpRequest proxyRequest) throws IOException {
|
||||
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
|
||||
String origin = servletRequest.getHeader("origin");
|
||||
response.setHeader("Access-Control-Allow-Origin",origin);
|
||||
response.setHeader("Access-Control-Allow-Credentials","true");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*/
|
||||
|
@ -4,8 +4,11 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.service.IPlatformService;
|
||||
import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@ -33,6 +36,7 @@ public class SipPlatformRunner implements CommandLineRunner {
|
||||
@Autowired
|
||||
private ISIPCommanderForPlatform sipCommanderForPlatform;
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
@ -50,9 +54,15 @@ public class SipPlatformRunner implements CommandLineRunner {
|
||||
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
|
||||
if (parentPlatformCatchOld != null) {
|
||||
// 取消订阅
|
||||
sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
|
||||
platformService.login(parentPlatform);
|
||||
});
|
||||
try {
|
||||
sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
|
||||
platformService.login(parentPlatform);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
|
||||
platformService.offline(parentPlatform, true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置所有平台离线
|
||||
|
@ -1,9 +1,12 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -26,10 +29,14 @@ public class SpringDocConfig {
|
||||
contact.setName("pan");
|
||||
contact.setEmail("648540858@qq.com");
|
||||
return new OpenAPI()
|
||||
.components(new Components()
|
||||
.addSecuritySchemes(JwtUtils.HEADER, new SecurityScheme()
|
||||
.type(SecurityScheme.Type.HTTP)
|
||||
.bearerFormat("JWT")))
|
||||
.info(new Info().title("WVP-PRO 接口文档")
|
||||
.contact(contact)
|
||||
.description("开箱即用的28181协议视频平台")
|
||||
.version("v2.0")
|
||||
.version("v3.1.0")
|
||||
.license(new License().name("Apache 2.0").url("http://springdoc.org")));
|
||||
}
|
||||
|
||||
|
@ -39,4 +39,6 @@ public class SystemInfoTimerTask {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -14,6 +16,9 @@ import java.util.List;
|
||||
@ConfigurationProperties(prefix = "user-settings", ignoreInvalidFields = true)
|
||||
@Order(0)
|
||||
public class UserSetting {
|
||||
@Getter
|
||||
@Setter
|
||||
private Boolean disableRealtimePlay = Boolean.FALSE;
|
||||
|
||||
private Boolean savePositionHistory = Boolean.FALSE;
|
||||
|
||||
@ -23,7 +28,7 @@ public class UserSetting {
|
||||
|
||||
private Integer playTimeout = 18000;
|
||||
|
||||
private int platformPlayTimeout = 60000;
|
||||
private int platformPlayTimeout = 20000;
|
||||
|
||||
private Boolean interfaceAuthentication = Boolean.TRUE;
|
||||
|
||||
@ -31,7 +36,7 @@ public class UserSetting {
|
||||
|
||||
private Boolean recordSip = Boolean.TRUE;
|
||||
|
||||
private Boolean logInDatebase = Boolean.TRUE;
|
||||
private Boolean logInDatabase = Boolean.TRUE;
|
||||
|
||||
private Boolean usePushingAsStatus = Boolean.TRUE;
|
||||
|
||||
@ -51,13 +56,11 @@ public class UserSetting {
|
||||
|
||||
private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
|
||||
|
||||
private Boolean deviceStatusNotify = Boolean.FALSE;
|
||||
private Boolean deviceStatusNotify = Boolean.TRUE;
|
||||
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
|
||||
|
||||
private String serverId = "000000";
|
||||
|
||||
private String recordPath = null;
|
||||
|
||||
private String thirdPartyGBIdReg = "[\\s\\S]*";
|
||||
|
||||
private String civilCodeFile = "classpath:civilCode.csv";
|
||||
@ -132,12 +135,12 @@ public class UserSetting {
|
||||
this.interfaceAuthenticationExcludes = interfaceAuthenticationExcludes;
|
||||
}
|
||||
|
||||
public Boolean getLogInDatebase() {
|
||||
return logInDatebase;
|
||||
public Boolean getLogInDatabase() {
|
||||
return logInDatabase;
|
||||
}
|
||||
|
||||
public void setLogInDatebase(Boolean logInDatebase) {
|
||||
this.logInDatebase = logInDatebase;
|
||||
public void setLogInDatabase(Boolean logInDatabase) {
|
||||
this.logInDatabase = logInDatabase;
|
||||
}
|
||||
|
||||
public String getServerId() {
|
||||
@ -252,14 +255,6 @@ public class UserSetting {
|
||||
this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
|
||||
public int getMaxNotifyCountQueue() {
|
||||
return maxNotifyCountQueue;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
// 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
|
||||
User user = new User();
|
||||
user.setId(jwtUser.getUserId());
|
||||
user.setUsername(jwtUser.getUserName());
|
||||
user.setPassword(jwtUser.getPassword());
|
||||
Role role = new Role();
|
||||
|
@ -1,8 +1,10 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.jose4j.jwk.RsaJwkGenerator;
|
||||
import org.jose4j.jws.AlgorithmIdentifiers;
|
||||
import org.jose4j.jws.JsonWebSignature;
|
||||
import org.jose4j.jwt.JwtClaims;
|
||||
@ -14,45 +16,69 @@ import org.jose4j.jwt.consumer.JwtConsumerBuilder;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
public class JwtUtils {
|
||||
@Component
|
||||
public class JwtUtils implements InitializingBean {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
|
||||
|
||||
private static final String HEADER = "access-token";
|
||||
public static final String HEADER = "access-token";
|
||||
|
||||
private static final String AUDIENCE = "Audience";
|
||||
|
||||
private static final long EXPIRED_THRESHOLD = 10 * 60;
|
||||
|
||||
private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
|
||||
private static final String privateKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\",\"d\":\"ed7U_k3rJ4yTk70JtRSIfjKGiEb67BO1TabcymnljKO7RU8nage84zZYuSu_XpQsHk6P1f0Gzxkicghm_Er-FrfVn2pp70Xu52z3yRd6BJUgWLDFk97ngScIyw5OiULKU9SrZk2frDpftNCSUcIgb50F8m0QAnBa_CdPsQKbuuhLv8V8tBAV7F_lAwvSBgu56wRo3hPz5dWH8YeXM7XBfQ9viFMNEKd21sP_j5C7ueUnXT66nBxe3ZJEU3iuMYM6D6dB_KW2GfZC6WmTgvGhhxJD0h7aYmfjkD99MDleB7SkpbvoODOqiQ5Epb7Nyh6kv5u4KUv2CJYtATLZkUeMkQ\",\"p\":\"uBUjWPWtlGksmOqsqCNWksfqJvMcnP_8TDYN7e4-WnHL4N-9HjRuPDnp6kHvCIEi9SEfxm7gNxlRcWegvNQr3IZCz7TnCTexXc5NOklB9OavWFla6u-s3Thn6Tz45-EUjpJr0VJMxhO-KxGmuTwUXBBp4vN6K2qV6rQNFmgkWzk\",\"q\":\"tW_i7cCec56bHkhITL_79dXHz_PLC_f7xlynmlZJGU_d6mqOKmLBNBbTMLnYW8uAFiFzWxDeDHh1o5uF0mSQR-Z1Fg35OftnpbWpy0Cbc2la5WgXQjOwtG1eLYIY2BD3-wQ1VYDBCvowr4FDi-sngxwLqvwmrJ0xjhi99O-Gzcs\",\"dp\":\"q1d5jE85Hz_6M-eTh_lEluEf0NtPEc-vvhw-QO4V-cecNpbrCBdTWBmr4dE3NdpFeJc5ZVFEv-SACyei1MBEh0ItI_pFZi4BmMfy2ELh8ptaMMkTOESYyVy8U7veDq9RnBcr5i1Nqr0rsBkA77-9T6gzdvycBZdzLYAkAmwzEvk\",\"dq\":\"q29A2K08Crs-jmp2Bi8Q_8QzvIX6wSBbwZ4ir24AO-5_HNP56IrPS0yV2GCB0pqCOGb6_Hz_koDvhtuYoqdqvMVAtMoXR3YJBUaVXPt65p4RyNmFwIPe31zHs_BNUTsXVRMw4c16mci03-Af1sEm4HdLfxAp6sfM3xr5wcnhcek\",\"qi\":\"rHPgVTyHUHuYzcxfouyBfb1XAY8nshwn0ddo81o1BccD4Z7zo5It6SefDHjxCAbcmbiCcXBSooLcY-NF5FMv3fg19UE21VyLQltHcVjRRp2tRs4OHcM8yaXIU2x6N6Z6BP2tOksHb9MOBY1wAQzFOAKg_G4Sxev6-_6ud6RISuc\"}";
|
||||
private static final String publicKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\"}";
|
||||
|
||||
/**
|
||||
* token过期时间(分钟)
|
||||
*/
|
||||
public static final long expirationTime = 30;
|
||||
public static final long expirationTime = 30 * 24 * 60;
|
||||
|
||||
public static String createToken(String username, String password, Integer roleId) {
|
||||
private static RsaJsonWebKey rsaJsonWebKey;
|
||||
|
||||
private static IUserService userService;
|
||||
|
||||
@Resource
|
||||
public void setUserService(IUserService userService) {
|
||||
JwtUtils.userService = userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
try {
|
||||
/**
|
||||
rsaJsonWebKey = generateRsaJsonWebKey();
|
||||
} catch (JoseException e) {
|
||||
logger.error("生成RsaJsonWebKey报错。", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建密钥对
|
||||
* @throws JoseException JoseException
|
||||
*/
|
||||
private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException {
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
return rsaJsonWebKey;
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
try {
|
||||
/*
|
||||
* “iss” (issuer) 发行人
|
||||
*
|
||||
* “sub” (subject) 主题
|
||||
*
|
||||
* “aud” (audience) 接收方 用户
|
||||
*
|
||||
* “exp” (expiration time) 到期时间
|
||||
*
|
||||
* “nbf” (not before) 在此之前不可用
|
||||
*
|
||||
* “iat” (issued at) jwt的签发时间
|
||||
*/
|
||||
//Payload
|
||||
JwtClaims claims = new JwtClaims();
|
||||
claims.setGeneratedJwtId();
|
||||
claims.setIssuedAtToNow();
|
||||
@ -62,9 +88,7 @@ public class JwtUtils {
|
||||
claims.setSubject("login");
|
||||
claims.setAudience(AUDIENCE);
|
||||
//添加自定义参数,必须是字符串类型
|
||||
claims.setClaim("username", username);
|
||||
claims.setClaim("password", password);
|
||||
claims.setClaim("roleId", roleId);
|
||||
claims.setClaim("userName", username);
|
||||
|
||||
//jws
|
||||
JsonWebSignature jws = new JsonWebSignature();
|
||||
@ -73,12 +97,10 @@ public class JwtUtils {
|
||||
jws.setKeyIdHeaderValue(keyId);
|
||||
jws.setPayload(claims.toJson());
|
||||
|
||||
PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyStr)).getPrivateKey();
|
||||
jws.setKey(privateKey);
|
||||
jws.setKey(rsaJsonWebKey.getPrivateKey());
|
||||
|
||||
//get token
|
||||
String idToken = jws.getCompactSerialization();
|
||||
return idToken;
|
||||
return jws.getCompactSerialization();
|
||||
} catch (JoseException e) {
|
||||
logger.error("[Token生成失败]: {}", e.getMessage());
|
||||
}
|
||||
@ -90,7 +112,6 @@ public class JwtUtils {
|
||||
return HEADER;
|
||||
}
|
||||
|
||||
|
||||
public static JwtUser verifyToken(String token) {
|
||||
|
||||
JwtUser jwtUser = new JwtUser();
|
||||
@ -103,7 +124,7 @@ public class JwtUtils {
|
||||
.setRequireSubject()
|
||||
//.setExpectedIssuer("")
|
||||
.setExpectedAudience(AUDIENCE)
|
||||
.setVerificationKey(new RsaJsonWebKey(JsonUtil.parseJson(publicKeyStr)).getPublicKey())
|
||||
.setVerificationKey(rsaJsonWebKey.getPublicKey())
|
||||
.build();
|
||||
|
||||
JwtClaims claims = consumer.processToClaims(token);
|
||||
@ -113,26 +134,27 @@ public class JwtUtils {
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
}else {
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
String username = (String) claims.getClaimValue("username");
|
||||
String password = (String) claims.getClaimValue("password");
|
||||
Long roleId = (Long) claims.getClaimValue("roleId");
|
||||
String username = (String) claims.getClaimValue("userName");
|
||||
User user = userService.getUserByUsername(username);
|
||||
|
||||
jwtUser.setUserName(username);
|
||||
jwtUser.setPassword(password);
|
||||
jwtUser.setRoleId(roleId.intValue());
|
||||
jwtUser.setPassword(user.getPassword());
|
||||
jwtUser.setRoleId(user.getRole().getId());
|
||||
jwtUser.setUserId(user.getId());
|
||||
|
||||
return jwtUser;
|
||||
} catch (InvalidJwtException e) {
|
||||
if (e.hasErrorCode(ErrorCodes.EXPIRED)) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
}else {
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION);
|
||||
}
|
||||
return jwtUser;
|
||||
}catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
logger.error("[Token解析失败]: {}", e.getMessage());
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
return jwtUser;
|
||||
|
@ -1,21 +0,0 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@SuppressWarnings({"unused"})
|
||||
@RequiredArgsConstructor
|
||||
public class RequestInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
log.info("{} 访问 {}",request.getRemoteHost(), request.getRequestURI());
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
private final RequestInterceptor requestInterceptor;
|
||||
@Override
|
||||
public void addInterceptors(@NotNull InterceptorRegistry registry) {
|
||||
registry.addInterceptor(requestInterceptor)
|
||||
.excludePathPatterns("/index/hook/**","/static/**")
|
||||
.addPathPatterns("/**");
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
@ -25,9 +25,11 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 配置Spring Security
|
||||
*
|
||||
* @author lin
|
||||
*/
|
||||
@Configuration
|
||||
@ -67,6 +69,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
matchers.add("/");
|
||||
matchers.add("/#/**");
|
||||
matchers.add("/static/**");
|
||||
matchers.add("/swagger-ui.html");
|
||||
matchers.add("/swagger-ui/");
|
||||
matchers.add("/index.html");
|
||||
matchers.add("/doc.html");
|
||||
matchers.add("/webjars/**");
|
||||
@ -75,7 +79,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
matchers.add("/js/**");
|
||||
matchers.add("/api/device/query/snap/**");
|
||||
matchers.add("/record_proxy/*/**");
|
||||
matchers.addAll(userSetting.getInterfaceAuthenticationExcludes());
|
||||
matchers.add("/api/emit");
|
||||
matchers.add("/favicon.ico");
|
||||
// 可以直接访问的静态数据
|
||||
web.ignoring().antMatchers(matchers.toArray(new String[0]));
|
||||
}
|
||||
@ -83,6 +88,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
/**
|
||||
* 配置认证方式
|
||||
*
|
||||
* @param auth
|
||||
* @throws Exception
|
||||
*/
|
||||
@ -111,7 +117,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.authorizeRequests()
|
||||
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
||||
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
|
||||
.antMatchers("/api/user/login","/index/hook/**","/zlm_Proxy/FhTuMYqB2HeCuNOb/record/t/1/2023-03-25/16:35:07-16:35:16-9353.mp4").permitAll()
|
||||
.antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
// 异常处理器
|
||||
.and()
|
||||
@ -124,18 +130,24 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
}
|
||||
|
||||
CorsConfigurationSource configurationSource(){
|
||||
CorsConfigurationSource configurationSource() {
|
||||
// 配置跨域
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("*"));
|
||||
corsConfiguration.setMaxAge(3600L);
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
|
||||
if (userSetting.getAllowedOrigins() != null && !userSetting.getAllowedOrigins().isEmpty()) {
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
|
||||
}else {
|
||||
corsConfiguration.setAllowCredentials(false);
|
||||
corsConfiguration.setAllowedOrigins(Collections.singletonList(CorsConfiguration.ALL));
|
||||
}
|
||||
|
||||
corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
|
||||
|
||||
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
|
||||
url.registerCorsConfiguration("/**",corsConfiguration);
|
||||
url.registerCorsConfiguration("/**", corsConfiguration);
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ public class JwtUser {
|
||||
EXCEPTION
|
||||
}
|
||||
|
||||
private int userId;
|
||||
private String userName;
|
||||
|
||||
private String password;
|
||||
@ -29,6 +30,14 @@ public class JwtUser {
|
||||
|
||||
private TokenStatus status;
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
@ -1,141 +1,141 @@
|
||||
package com.genersoft.iot.vmp.gb28181;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@Order(value=10)
|
||||
public class SipLayer implements CommandLineRunner {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private ISIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
List<String> monitorIps = new ArrayList<>();
|
||||
// 使用逗号分割多个ip
|
||||
String separator = ",";
|
||||
if (sipConfig.getIp().indexOf(separator) > 0) {
|
||||
String[] split = sipConfig.getIp().split(separator);
|
||||
monitorIps.addAll(Arrays.asList(split));
|
||||
}else {
|
||||
monitorIps.add(sipConfig.getIp());
|
||||
}
|
||||
|
||||
SipFactory.getInstance().setPathName("gov.nist");
|
||||
if (monitorIps.size() > 0) {
|
||||
for (String monitorIp : monitorIps) {
|
||||
addListeningPoint(monitorIp, sipConfig.getPort());
|
||||
}
|
||||
if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addListeningPoint(String monitorIp, int port){
|
||||
SipStackImpl sipStack;
|
||||
try {
|
||||
sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog()));
|
||||
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
|
||||
} catch (PeerUnavailableException e) {
|
||||
logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");
|
||||
SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||
|
||||
tcpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||
tcpSipProviderMap.put(monitorIp, tcpSipProvider);
|
||||
logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
logger.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");
|
||||
|
||||
SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||
|
||||
udpSipProviderMap.put(monitorIp, udpSipProvider);
|
||||
|
||||
logger.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
logger.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider(String ip) {
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider() {
|
||||
if (udpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider() {
|
||||
if (tcpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider(String ip) {
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public String getLocalIp(String deviceLocalIp) {
|
||||
if (!ObjectUtils.isEmpty(deviceLocalIp)) {
|
||||
return deviceLocalIp;
|
||||
}
|
||||
return getUdpSipProvider().getListeningPoint().getIPAddress();
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
|
||||
import gov.nist.javax.sip.SipProviderImpl;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@Order(value=10)
|
||||
public class SipLayer implements CommandLineRunner {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private ISIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
List<String> monitorIps = new ArrayList<>();
|
||||
// 使用逗号分割多个ip
|
||||
String separator = ",";
|
||||
if (sipConfig.getIp().indexOf(separator) > 0) {
|
||||
String[] split = sipConfig.getIp().split(separator);
|
||||
monitorIps.addAll(Arrays.asList(split));
|
||||
}else {
|
||||
monitorIps.add(sipConfig.getIp());
|
||||
}
|
||||
|
||||
SipFactory.getInstance().setPathName("gov.nist");
|
||||
if (monitorIps.size() > 0) {
|
||||
for (String monitorIp : monitorIps) {
|
||||
addListeningPoint(monitorIp, sipConfig.getPort());
|
||||
}
|
||||
if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addListeningPoint(String monitorIp, int port){
|
||||
SipStackImpl sipStack;
|
||||
try {
|
||||
sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog()));
|
||||
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
|
||||
} catch (PeerUnavailableException e) {
|
||||
logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");
|
||||
SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
|
||||
|
||||
tcpSipProvider.setDialogErrorsAutomaticallyHandled();
|
||||
tcpSipProvider.addSipListener(sipProcessorObserver);
|
||||
tcpSipProviderMap.put(monitorIp, tcpSipProvider);
|
||||
logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
logger.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
|
||||
try {
|
||||
ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");
|
||||
|
||||
SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(sipProcessorObserver);
|
||||
|
||||
udpSipProviderMap.put(monitorIp, udpSipProvider);
|
||||
|
||||
logger.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port);
|
||||
} catch (TransportNotSupportedException
|
||||
| TooManyListenersException
|
||||
| ObjectInUseException
|
||||
| InvalidArgumentException e) {
|
||||
logger.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
|
||||
, monitorIp, port);
|
||||
}
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider(String ip) {
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public SipProviderImpl getUdpSipProvider() {
|
||||
if (udpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return udpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider() {
|
||||
if (tcpSipProviderMap.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.values().stream().findFirst().get();
|
||||
}
|
||||
|
||||
public SipProviderImpl getTcpSipProvider(String ip) {
|
||||
if (ObjectUtils.isEmpty(ip)) {
|
||||
return null;
|
||||
}
|
||||
return tcpSipProviderMap.get(ip);
|
||||
}
|
||||
|
||||
public String getLocalIp(String deviceLocalIp) {
|
||||
if (!ObjectUtils.isEmpty(deviceLocalIp)) {
|
||||
return deviceLocalIp;
|
||||
}
|
||||
return getUdpSipProvider().getListeningPoint().getIPAddress();
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@
|
||||
package com.genersoft.iot.vmp.gb28181.auth;
|
||||
|
||||
import gov.nist.core.InternalErrorHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sip.address.URI;
|
||||
import javax.sip.header.AuthorizationHeader;
|
||||
@ -46,14 +46,19 @@ import java.util.Random;
|
||||
* @author M. Ranganathan
|
||||
* @author Marc Bednarek
|
||||
*/
|
||||
@Slf4j
|
||||
|
||||
public class DigestServerAuthenticationHelper {
|
||||
private final MessageDigest messageDigest;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(DigestServerAuthenticationHelper.class);
|
||||
|
||||
private MessageDigest messageDigest;
|
||||
|
||||
public static final String DEFAULT_ALGORITHM = "MD5";
|
||||
public static final String DEFAULT_SCHEME = "Digest";
|
||||
|
||||
|
||||
|
||||
|
||||
/** to hex converter */
|
||||
private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
@ -88,8 +93,8 @@ public class DigestServerAuthenticationHelper {
|
||||
long pad = rand.nextLong();
|
||||
String nonceString = Long.valueOf(time).toString()
|
||||
+ Long.valueOf(pad).toString();
|
||||
byte[] mdBytes = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdBytes);
|
||||
byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdbytes);
|
||||
}
|
||||
|
||||
public Response generateChallenge(HeaderFactory headerFactory, Response response, String realm) {
|
||||
@ -133,9 +138,12 @@ public class DigestServerAuthenticationHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri;
|
||||
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
String HA1 = hashedPassword;
|
||||
|
||||
|
||||
byte[] mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
|
||||
@ -169,7 +177,7 @@ public class DigestServerAuthenticationHelper {
|
||||
String realm = authHeader.getRealm().trim();
|
||||
String username = authHeader.getUsername().trim();
|
||||
|
||||
if(ObjectUtils.anyNull(username,realm)){
|
||||
if ( username == null || realm == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -188,22 +196,26 @@ public class DigestServerAuthenticationHelper {
|
||||
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||
int nc = authHeader.getNonceCount();
|
||||
String ncStr = String.format("%08x", nc).toUpperCase();
|
||||
String A1 = String.join(":",username , realm , pass);
|
||||
String A2 = String.join(":",request.getMethod().toUpperCase() , uri.toString());
|
||||
// String ncStr = new DecimalFormat("00000000").format(nc);
|
||||
// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16));
|
||||
|
||||
byte[] mdbytes = messageDigest.digest(A1.getBytes());
|
||||
String A1 = username + ":" + realm + ":" + pass;
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
|
||||
byte mdbytes[] = messageDigest.digest(A1.getBytes());
|
||||
String HA1 = toHexString(mdbytes);
|
||||
log.debug("A1: " + A1);
|
||||
log.debug("A2: " + A2);
|
||||
logger.debug("A1: " + A1);
|
||||
logger.debug("A2: " + A2);
|
||||
mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
log.debug("HA1: " + HA1);
|
||||
log.debug("HA2: " + HA2);
|
||||
logger.debug("HA1: " + HA1);
|
||||
logger.debug("HA2: " + HA2);
|
||||
// String cnonce = authHeader.getCNonce();
|
||||
log.debug("nonce: " + nonce);
|
||||
log.debug("nc: " + ncStr);
|
||||
log.debug("cnonce: " + cnonce);
|
||||
log.debug("qop: " + qop);
|
||||
logger.debug("nonce: " + nonce);
|
||||
logger.debug("nc: " + ncStr);
|
||||
logger.debug("cnonce: " + cnonce);
|
||||
logger.debug("qop: " + qop);
|
||||
String KD = HA1 + ":" + nonce;
|
||||
|
||||
if (qop != null && qop.equalsIgnoreCase("auth") ) {
|
||||
@ -216,12 +228,12 @@ public class DigestServerAuthenticationHelper {
|
||||
KD += ":" + qop;
|
||||
}
|
||||
KD += ":" + HA2;
|
||||
log.debug("KD: " + KD);
|
||||
logger.debug("KD: " + KD);
|
||||
mdbytes = messageDigest.digest(KD.getBytes());
|
||||
String mdString = toHexString(mdbytes);
|
||||
log.debug("mdString: " + mdString);
|
||||
logger.debug("mdString: " + mdString);
|
||||
String response = authHeader.getResponse();
|
||||
log.debug("response: " + response);
|
||||
logger.debug("response: " + response);
|
||||
return mdString.equals(response);
|
||||
|
||||
}
|
||||
|
@ -1,187 +1,187 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Schema(description = "报警信息")
|
||||
public class DeviceAlarm {
|
||||
|
||||
/**
|
||||
* 数据库id
|
||||
*/
|
||||
@Schema(description = "数据库id")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 设备Id
|
||||
*/
|
||||
@Schema(description = "设备的国标编号")
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 通道Id
|
||||
*/
|
||||
@Schema(description = "通道的国标编号")
|
||||
private String channelId;
|
||||
|
||||
/**
|
||||
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情
|
||||
*/
|
||||
@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
|
||||
private String alarmPriority;
|
||||
|
||||
/**
|
||||
* 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
||||
* 7其他报警;可以为直接组合如12为电话报警或 设备报警-
|
||||
*/
|
||||
@Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" +
|
||||
"\t * 7其他报警;可以为直接组合如12为电话报警或设备报警")
|
||||
private String alarmMethod;
|
||||
|
||||
/**
|
||||
* 报警时间
|
||||
*/
|
||||
@Schema(description = "报警时间")
|
||||
private String alarmTime;
|
||||
|
||||
/**
|
||||
* 报警内容描述
|
||||
*/
|
||||
@Schema(description = "报警内容描述")
|
||||
private String alarmDescription;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@Schema(description = "经度")
|
||||
private double longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
@Schema(description = "纬度")
|
||||
private double latitude;
|
||||
|
||||
/**
|
||||
* 报警类型,
|
||||
* 报警方式为2时,不携带 AlarmType为默认的报警设备报警,
|
||||
* 携带 AlarmType取值及对应报警类型如下:
|
||||
* 1-视频丢失报警;
|
||||
* 2-设备防拆报警;
|
||||
* 3-存储设备磁盘满报警;
|
||||
* 4-设备高温报警;
|
||||
* 5-设备低温报警。
|
||||
* 报警方式为5时,取值如下:
|
||||
* 1-人工视频报警;
|
||||
* 2-运动目标检测报警;
|
||||
* 3-遗留物检测报警;
|
||||
* 4-物体移除检测报警;
|
||||
* 5-绊线检测报警;
|
||||
* 6-入侵检测报警;
|
||||
* 7-逆行检测报警;
|
||||
* 8-徘徊检测报警;
|
||||
* 9-流量统计报警;
|
||||
* 10-密度检测报警;
|
||||
* 11-视频异常检测报警;
|
||||
* 12-快速移动报警。
|
||||
* 报警方式为6时,取值下:
|
||||
* 1-存储设备磁盘故障报警;
|
||||
* 2-存储设备风扇故障报警。
|
||||
*/
|
||||
@Schema(description = "报警类型")
|
||||
private String alarmType;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getAlarmPriority() {
|
||||
return alarmPriority;
|
||||
}
|
||||
|
||||
public void setAlarmPriority(String alarmPriority) {
|
||||
this.alarmPriority = alarmPriority;
|
||||
}
|
||||
|
||||
public String getAlarmMethod() {
|
||||
return alarmMethod;
|
||||
}
|
||||
|
||||
public void setAlarmMethod(String alarmMethod) {
|
||||
this.alarmMethod = alarmMethod;
|
||||
}
|
||||
|
||||
public String getAlarmTime() {
|
||||
return alarmTime;
|
||||
}
|
||||
|
||||
public void setAlarmTime(String alarmTime) {
|
||||
this.alarmTime = alarmTime;
|
||||
}
|
||||
|
||||
public String getAlarmDescription() {
|
||||
return alarmDescription;
|
||||
}
|
||||
|
||||
public void setAlarmDescription(String alarmDescription) {
|
||||
this.alarmDescription = alarmDescription;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public String getAlarmType() {
|
||||
return alarmType;
|
||||
}
|
||||
|
||||
public void setAlarmType(String alarmType) {
|
||||
this.alarmType = alarmType;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(String createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Schema(description = "报警信息")
|
||||
public class DeviceAlarm {
|
||||
|
||||
/**
|
||||
* 数据库id
|
||||
*/
|
||||
@Schema(description = "数据库id")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 设备Id
|
||||
*/
|
||||
@Schema(description = "设备的国标编号")
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 通道Id
|
||||
*/
|
||||
@Schema(description = "通道的国标编号")
|
||||
private String channelId;
|
||||
|
||||
/**
|
||||
* 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情
|
||||
*/
|
||||
@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
|
||||
private String alarmPriority;
|
||||
|
||||
/**
|
||||
* 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
|
||||
* 7其他报警;可以为直接组合如12为电话报警或 设备报警-
|
||||
*/
|
||||
@Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" +
|
||||
"\t * 7其他报警;可以为直接组合如12为电话报警或设备报警")
|
||||
private String alarmMethod;
|
||||
|
||||
/**
|
||||
* 报警时间
|
||||
*/
|
||||
@Schema(description = "报警时间")
|
||||
private String alarmTime;
|
||||
|
||||
/**
|
||||
* 报警内容描述
|
||||
*/
|
||||
@Schema(description = "报警内容描述")
|
||||
private String alarmDescription;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@Schema(description = "经度")
|
||||
private double longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
@Schema(description = "纬度")
|
||||
private double latitude;
|
||||
|
||||
/**
|
||||
* 报警类型,
|
||||
* 报警方式为2时,不携带 AlarmType为默认的报警设备报警,
|
||||
* 携带 AlarmType取值及对应报警类型如下:
|
||||
* 1-视频丢失报警;
|
||||
* 2-设备防拆报警;
|
||||
* 3-存储设备磁盘满报警;
|
||||
* 4-设备高温报警;
|
||||
* 5-设备低温报警。
|
||||
* 报警方式为5时,取值如下:
|
||||
* 1-人工视频报警;
|
||||
* 2-运动目标检测报警;
|
||||
* 3-遗留物检测报警;
|
||||
* 4-物体移除检测报警;
|
||||
* 5-绊线检测报警;
|
||||
* 6-入侵检测报警;
|
||||
* 7-逆行检测报警;
|
||||
* 8-徘徊检测报警;
|
||||
* 9-流量统计报警;
|
||||
* 10-密度检测报警;
|
||||
* 11-视频异常检测报警;
|
||||
* 12-快速移动报警。
|
||||
* 报警方式为6时,取值下:
|
||||
* 1-存储设备磁盘故障报警;
|
||||
* 2-存储设备风扇故障报警。
|
||||
*/
|
||||
@Schema(description = "报警类型")
|
||||
private String alarmType;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getAlarmPriority() {
|
||||
return alarmPriority;
|
||||
}
|
||||
|
||||
public void setAlarmPriority(String alarmPriority) {
|
||||
this.alarmPriority = alarmPriority;
|
||||
}
|
||||
|
||||
public String getAlarmMethod() {
|
||||
return alarmMethod;
|
||||
}
|
||||
|
||||
public void setAlarmMethod(String alarmMethod) {
|
||||
this.alarmMethod = alarmMethod;
|
||||
}
|
||||
|
||||
public String getAlarmTime() {
|
||||
return alarmTime;
|
||||
}
|
||||
|
||||
public void setAlarmTime(String alarmTime) {
|
||||
this.alarmTime = alarmTime;
|
||||
}
|
||||
|
||||
public String getAlarmDescription() {
|
||||
return alarmDescription;
|
||||
}
|
||||
|
||||
public void setAlarmDescription(String alarmDescription) {
|
||||
this.alarmDescription = alarmDescription;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public String getAlarmType() {
|
||||
return alarmType;
|
||||
}
|
||||
|
||||
public void setAlarmType(String alarmType) {
|
||||
this.alarmType = alarmType;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(String createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HomePositionRequest.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HomePositionRequest.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamCallback.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamCallback.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/MobilePosition.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/MobilePosition.java
Normal file → Executable file
11
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
Normal file → Executable file
11
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
Normal file → Executable file
@ -186,6 +186,9 @@ public class ParentPlatform {
|
||||
@Schema(description = "是否作为消息通道")
|
||||
private boolean asMessageChannel;
|
||||
|
||||
@Schema(description = "是否作为消息通道")
|
||||
private boolean autoPushChannel;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
@ -425,4 +428,12 @@ public class ParentPlatform {
|
||||
public void setAsMessageChannel(boolean asMessageChannel) {
|
||||
this.asMessageChannel = asMessageChannel;
|
||||
}
|
||||
|
||||
public boolean isAutoPushChannel() {
|
||||
return autoPushChannel;
|
||||
}
|
||||
|
||||
public void setAutoPushChannel(boolean autoPushChannel) {
|
||||
this.autoPushChannel = autoPushChannel;
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java
Normal file → Executable file
204
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
Normal file → Executable file
204
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
Normal file → Executable file
@ -1,102 +1,102 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:设备录像信息bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:05:56
|
||||
*/
|
||||
@Schema(description = "设备录像查询结果信息")
|
||||
public class RecordInfo {
|
||||
|
||||
@Schema(description = "设备编号")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "通道编号")
|
||||
private String channelId;
|
||||
|
||||
@Schema(description = "命令序列号")
|
||||
private String sn;
|
||||
|
||||
@Schema(description = "设备名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "列表总数")
|
||||
private int sumNum;
|
||||
|
||||
private int count;
|
||||
|
||||
private Instant lastTime;
|
||||
|
||||
@Schema(description = "")
|
||||
private List<RecordItem> recordList;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSumNum() {
|
||||
return sumNum;
|
||||
}
|
||||
|
||||
public void setSumNum(int sumNum) {
|
||||
this.sumNum = sumNum;
|
||||
}
|
||||
|
||||
public List<RecordItem> getRecordList() {
|
||||
return recordList;
|
||||
}
|
||||
|
||||
public void setRecordList(List<RecordItem> recordList) {
|
||||
this.recordList = recordList;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(String sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
public Instant getLastTime() {
|
||||
return lastTime;
|
||||
}
|
||||
|
||||
public void setLastTime(Instant lastTime) {
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:设备录像信息bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:05:56
|
||||
*/
|
||||
@Schema(description = "设备录像查询结果信息")
|
||||
public class RecordInfo {
|
||||
|
||||
@Schema(description = "设备编号")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "通道编号")
|
||||
private String channelId;
|
||||
|
||||
@Schema(description = "命令序列号")
|
||||
private String sn;
|
||||
|
||||
@Schema(description = "设备名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "列表总数")
|
||||
private int sumNum;
|
||||
|
||||
private int count;
|
||||
|
||||
private Instant lastTime;
|
||||
|
||||
@Schema(description = "")
|
||||
private List<RecordItem> recordList;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSumNum() {
|
||||
return sumNum;
|
||||
}
|
||||
|
||||
public void setSumNum(int sumNum) {
|
||||
this.sumNum = sumNum;
|
||||
}
|
||||
|
||||
public List<RecordItem> getRecordList() {
|
||||
return recordList;
|
||||
}
|
||||
|
||||
public void setRecordList(List<RecordItem> recordList) {
|
||||
this.recordList = recordList;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(String sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
public Instant getLastTime() {
|
||||
return lastTime;
|
||||
}
|
||||
|
||||
public void setLastTime(Instant lastTime) {
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
|
288
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
Normal file → Executable file
288
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
Normal file → Executable file
@ -1,144 +1,144 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
* @description:设备录像bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:06:54
|
||||
*/
|
||||
@Schema(description = "设备录像详情")
|
||||
public class RecordItem implements Comparable<RecordItem>{
|
||||
|
||||
@Schema(description = "设备编号")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件路径名 (可选)")
|
||||
private String filePath;
|
||||
|
||||
@Schema(description = "录像文件大小,单位:Byte(可选)")
|
||||
private String fileSize;
|
||||
|
||||
@Schema(description = "录像地址(可选)")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "录像开始时间(可选)")
|
||||
private String startTime;
|
||||
|
||||
@Schema(description = "录像结束时间(可选)")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
|
||||
private int secrecy;
|
||||
|
||||
@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "录像触发者ID(可选)")
|
||||
private String recorderId;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(String startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public String getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public int getSecrecy() {
|
||||
return secrecy;
|
||||
}
|
||||
|
||||
public void setSecrecy(int secrecy) {
|
||||
this.secrecy = secrecy;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getRecorderId() {
|
||||
return recorderId;
|
||||
}
|
||||
|
||||
public void setRecorderId(String recorderId) {
|
||||
this.recorderId = recorderId;
|
||||
}
|
||||
|
||||
public String getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(String fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull RecordItem recordItem) {
|
||||
TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime);
|
||||
TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime());
|
||||
Instant startTimeParamInstant = Instant.from(startTimeParam);
|
||||
Instant startTimeNowInstant = Instant.from(startTimeNow);
|
||||
if (startTimeNowInstant.equals(startTimeParamInstant)) {
|
||||
return 0;
|
||||
}else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) {
|
||||
return -1;
|
||||
}else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
* @description:设备录像bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:06:54
|
||||
*/
|
||||
@Schema(description = "设备录像详情")
|
||||
public class RecordItem implements Comparable<RecordItem>{
|
||||
|
||||
@Schema(description = "设备编号")
|
||||
private String deviceId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件路径名 (可选)")
|
||||
private String filePath;
|
||||
|
||||
@Schema(description = "录像文件大小,单位:Byte(可选)")
|
||||
private String fileSize;
|
||||
|
||||
@Schema(description = "录像地址(可选)")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "录像开始时间(可选)")
|
||||
private String startTime;
|
||||
|
||||
@Schema(description = "录像结束时间(可选)")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
|
||||
private int secrecy;
|
||||
|
||||
@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "录像触发者ID(可选)")
|
||||
private String recorderId;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(String startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public String getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public int getSecrecy() {
|
||||
return secrecy;
|
||||
}
|
||||
|
||||
public void setSecrecy(int secrecy) {
|
||||
this.secrecy = secrecy;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getRecorderId() {
|
||||
return recorderId;
|
||||
}
|
||||
|
||||
public void setRecorderId(String recorderId) {
|
||||
this.recorderId = recorderId;
|
||||
}
|
||||
|
||||
public String getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(String fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull RecordItem recordItem) {
|
||||
TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime);
|
||||
TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime());
|
||||
Instant startTimeParamInstant = Instant.from(startTimeParam);
|
||||
Instant startTimeNowInstant = Instant.from(startTimeNow);
|
||||
if (startTimeNowInstant.equals(startTimeParamInstant)) {
|
||||
return 0;
|
||||
}else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) {
|
||||
return -1;
|
||||
}else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SDPInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SDPInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
Normal file → Executable file
36
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
Normal file → Executable file
36
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
Normal file → Executable file
@ -2,12 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.service.IPlatformService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -24,6 +21,9 @@ public class SubscribeHolder {
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
private final String taskOverduePrefix = "subscribe_overdue_";
|
||||
|
||||
private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
|
||||
@ -32,11 +32,13 @@ public class SubscribeHolder {
|
||||
|
||||
public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
|
||||
catalogMap.put(platformId, subscribeInfo);
|
||||
// 添加订阅到期
|
||||
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
|
||||
// 添加任务处理订阅过期
|
||||
dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
|
||||
subscribeInfo.getExpires() * 1000);
|
||||
if (subscribeInfo.getExpires() > 0) {
|
||||
// 添加订阅到期
|
||||
String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
|
||||
// 添加任务处理订阅过期
|
||||
dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
|
||||
subscribeInfo.getExpires() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public SubscribeInfo getCatalogSubscribe(String platformId) {
|
||||
@ -58,16 +60,18 @@ public class SubscribeHolder {
|
||||
|
||||
public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
|
||||
mobilePositionMap.put(platformId, subscribeInfo);
|
||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
|
||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
|
||||
// 添加任务处理GPS定时推送
|
||||
dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId),
|
||||
subscribeInfo.getGpsInterval() * 1000);
|
||||
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
|
||||
// 添加任务处理订阅过期
|
||||
dynamicTask.startDelay(taskOverdueKey, () -> {
|
||||
removeMobilePositionSubscribe(subscribeInfo.getId());
|
||||
},
|
||||
subscribeInfo.getExpires() * 1000);
|
||||
if (subscribeInfo.getExpires() > 0) {
|
||||
// 添加任务处理订阅过期
|
||||
dynamicTask.startDelay(taskOverdueKey, () -> {
|
||||
removeMobilePositionSubscribe(subscribeInfo.getId());
|
||||
},
|
||||
subscribeInfo.getExpires() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public SubscribeInfo getMobilePositionSubscribe(String platformId) {
|
||||
@ -76,7 +80,7 @@ public class SubscribeHolder {
|
||||
|
||||
public void removeMobilePositionSubscribe(String platformId) {
|
||||
mobilePositionMap.remove(platformId);
|
||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
|
||||
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId;
|
||||
// 结束任务处理GPS定时推送
|
||||
dynamicTask.stop(key);
|
||||
String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
|
||||
|
42
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
Normal file → Executable file
42
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
Normal file → Executable file
@ -18,6 +18,9 @@ public class SubscribeInfo {
|
||||
|
||||
}
|
||||
|
||||
public SubscribeInfo() {
|
||||
}
|
||||
|
||||
private String id;
|
||||
|
||||
private SIPRequest request;
|
||||
@ -33,6 +36,21 @@ public class SubscribeInfo {
|
||||
private String sn;
|
||||
private int gpsInterval;
|
||||
|
||||
/**
|
||||
* 模拟的FromTag
|
||||
*/
|
||||
private String simulatedFromTag;
|
||||
|
||||
/**
|
||||
* 模拟的ToTag
|
||||
*/
|
||||
private String simulatedToTag;
|
||||
|
||||
/**
|
||||
* 模拟的CallID
|
||||
*/
|
||||
private String simulatedCallId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@ -96,4 +114,28 @@ public class SubscribeInfo {
|
||||
public void setGpsInterval(int gpsInterval) {
|
||||
this.gpsInterval = gpsInterval;
|
||||
}
|
||||
|
||||
public String getSimulatedFromTag() {
|
||||
return simulatedFromTag;
|
||||
}
|
||||
|
||||
public void setSimulatedFromTag(String simulatedFromTag) {
|
||||
this.simulatedFromTag = simulatedFromTag;
|
||||
}
|
||||
|
||||
public String getSimulatedCallId() {
|
||||
return simulatedCallId;
|
||||
}
|
||||
|
||||
public void setSimulatedCallId(String simulatedCallId) {
|
||||
this.simulatedCallId = simulatedCallId;
|
||||
}
|
||||
|
||||
public String getSimulatedToTag() {
|
||||
return simulatedToTag;
|
||||
}
|
||||
|
||||
public void setSimulatedToTag(String simulatedToTag) {
|
||||
this.simulatedToTag = simulatedToTag;
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java
Normal file → Executable file
176
src/main/java/com/genersoft/iot/vmp/gb28181/conf/StackLoggerImpl.java
Normal file → Executable file
176
src/main/java/com/genersoft/iot/vmp/gb28181/conf/StackLoggerImpl.java
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
package com.genersoft.iot.vmp.gb28181.conf;
|
||||
|
||||
import gov.nist.core.StackLogger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.spi.LocationAwareLogger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Properties;
|
||||
@ -10,100 +10,132 @@ import java.util.Properties;
|
||||
@Component
|
||||
public class StackLoggerImpl implements StackLogger {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(StackLoggerImpl.class);
|
||||
/**
|
||||
* 完全限定类名(Fully Qualified Class Name),用于定位日志位置
|
||||
*/
|
||||
private static final String FQCN = StackLoggerImpl.class.getName();
|
||||
|
||||
@Override
|
||||
public void logStackTrace() {
|
||||
/**
|
||||
* 获取栈中类信息(以便底层日志记录系统能够提取正确的位置信息(方法名、行号))
|
||||
* @return LocationAwareLogger
|
||||
*/
|
||||
private static LocationAwareLogger getLocationAwareLogger() {
|
||||
return (LocationAwareLogger) LoggerFactory.getLogger(new Throwable().getStackTrace()[4].getClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logStackTrace(int traceLevel) {
|
||||
System.out.println("traceLevel: " + traceLevel);
|
||||
}
|
||||
/**
|
||||
* 封装打印日志的位置信息
|
||||
* @param level 日志级别
|
||||
* @param message 日志事件的消息
|
||||
*/
|
||||
private static void log(int level, String message) {
|
||||
LocationAwareLogger locationAwareLogger = getLocationAwareLogger();
|
||||
locationAwareLogger.log(null, FQCN, level, message, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineCount() {
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* 封装打印日志的位置信息
|
||||
* @param level 日志级别
|
||||
* @param message 日志事件的消息
|
||||
*/
|
||||
private static void log(int level, String message, Throwable throwable) {
|
||||
LocationAwareLogger locationAwareLogger = getLocationAwareLogger();
|
||||
locationAwareLogger.log(null, FQCN, level, message, null, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logException(Throwable ex) {
|
||||
@Override
|
||||
public void logStackTrace() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
// logger.debug(message);
|
||||
}
|
||||
@Override
|
||||
public void logStackTrace(int traceLevel) {
|
||||
System.out.println("traceLevel: " + traceLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message, Exception ex) {
|
||||
// logger.debug(message);
|
||||
}
|
||||
@Override
|
||||
public int getLineCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logTrace(String message) {
|
||||
logger.trace(message);
|
||||
}
|
||||
@Override
|
||||
public void logException(Throwable ex) {
|
||||
|
||||
@Override
|
||||
public void logFatalError(String message) {
|
||||
// logger.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message) {
|
||||
// logger.error(message);
|
||||
}
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void logDebug(String message, Exception ex) {
|
||||
log(LocationAwareLogger.INFO_INT, message, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled(int logLevel) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void logTrace(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message, Exception ex) {
|
||||
// logger.error(message);
|
||||
}
|
||||
@Override
|
||||
public void logFatalError(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
logger.warn(message);
|
||||
}
|
||||
@Override
|
||||
public void logError(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableLogging() {
|
||||
@Override
|
||||
public boolean isLoggingEnabled(int logLevel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void logError(String message, Exception ex) {
|
||||
log(LocationAwareLogger.INFO_INT, message, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLogging() {
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void logInfo(String message) {
|
||||
log(LocationAwareLogger.INFO_INT, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBuildTimeStamp(String buildTimeStamp) {
|
||||
@Override
|
||||
public void disableLogging() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackProperties(Properties stackProperties) {
|
||||
@Override
|
||||
public void enableLogging() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoggerName() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void setBuildTimeStamp(String buildTimeStamp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStackProperties(Properties stackProperties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoggerName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
236
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
Normal file → Executable file
236
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
Normal file → Executable file
@ -1,118 +1,118 @@
|
||||
package com.genersoft.iot.vmp.gb28181.event;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
|
||||
|
||||
import javax.sip.TimeoutEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @description:Event事件通知推送器,支持推送在线事件、离线事件
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月6日 上午11:30:50
|
||||
*/
|
||||
@Component
|
||||
public class EventPublisher {
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
/**
|
||||
* 设备报警事件
|
||||
* @param deviceAlarm
|
||||
*/
|
||||
public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) {
|
||||
AlarmEvent alarmEvent = new AlarmEvent(this);
|
||||
alarmEvent.setAlarmInfo(deviceAlarm);
|
||||
applicationEventPublisher.publishEvent(alarmEvent);
|
||||
}
|
||||
|
||||
public void zlmOfflineEventPublish(String mediaServerId){
|
||||
ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this);
|
||||
outEvent.setMediaServerId(mediaServerId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
public void zlmOnlineEventPublish(String mediaServerId) {
|
||||
ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this);
|
||||
outEvent.setMediaServerId(mediaServerId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) {
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
deviceChannelList.add(deviceChannel);
|
||||
catalogEventPublish(platformId, deviceChannelList, type);
|
||||
}
|
||||
|
||||
|
||||
public void requestTimeOut(TimeoutEvent timeoutEvent) {
|
||||
RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this);
|
||||
requestTimeoutEvent.setTimeoutEvent(timeoutEvent);
|
||||
applicationEventPublisher.publishEvent(requestTimeoutEvent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param platformId
|
||||
* @param deviceChannels
|
||||
* @param type
|
||||
*/
|
||||
public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
|
||||
CatalogEvent outEvent = new CatalogEvent(this);
|
||||
List<DeviceChannel> channels = new ArrayList<>();
|
||||
if (deviceChannels.size() > 1) {
|
||||
// 数据去重
|
||||
Set<String> gbIdSet = new HashSet<>();
|
||||
for (DeviceChannel deviceChannel : deviceChannels) {
|
||||
if (!gbIdSet.contains(deviceChannel.getChannelId())) {
|
||||
gbIdSet.add(deviceChannel.getChannelId());
|
||||
channels.add(deviceChannel);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
channels = deviceChannels;
|
||||
}
|
||||
outEvent.setDeviceChannels(channels);
|
||||
outEvent.setType(type);
|
||||
outEvent.setPlatformId(platformId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) {
|
||||
CatalogEvent outEvent = new CatalogEvent(this);
|
||||
outEvent.setGbStreams(gbStreams);
|
||||
outEvent.setType(type);
|
||||
outEvent.setPlatformId(platformId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) {
|
||||
List<GbStream> gbStreamList = new ArrayList<>();
|
||||
gbStreamList.add(gbStream);
|
||||
catalogEventPublishForStream(platformId, gbStreamList, type);
|
||||
}
|
||||
|
||||
public void recordEndEventPush(RecordInfo recordInfo) {
|
||||
RecordEndEvent outEvent = new RecordEndEvent(this);
|
||||
outEvent.setRecordInfo(recordInfo);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.event;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
|
||||
|
||||
import javax.sip.TimeoutEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @description:Event事件通知推送器,支持推送在线事件、离线事件
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月6日 上午11:30:50
|
||||
*/
|
||||
@Component
|
||||
public class EventPublisher {
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
/**
|
||||
* 设备报警事件
|
||||
* @param deviceAlarm
|
||||
*/
|
||||
public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) {
|
||||
AlarmEvent alarmEvent = new AlarmEvent(this);
|
||||
alarmEvent.setAlarmInfo(deviceAlarm);
|
||||
applicationEventPublisher.publishEvent(alarmEvent);
|
||||
}
|
||||
|
||||
public void zlmOfflineEventPublish(String mediaServerId){
|
||||
ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this);
|
||||
outEvent.setMediaServerId(mediaServerId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
public void zlmOnlineEventPublish(String mediaServerId) {
|
||||
ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this);
|
||||
outEvent.setMediaServerId(mediaServerId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) {
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
deviceChannelList.add(deviceChannel);
|
||||
catalogEventPublish(platformId, deviceChannelList, type);
|
||||
}
|
||||
|
||||
|
||||
public void requestTimeOut(TimeoutEvent timeoutEvent) {
|
||||
RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this);
|
||||
requestTimeoutEvent.setTimeoutEvent(timeoutEvent);
|
||||
applicationEventPublisher.publishEvent(requestTimeoutEvent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param platformId
|
||||
* @param deviceChannels
|
||||
* @param type
|
||||
*/
|
||||
public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
|
||||
CatalogEvent outEvent = new CatalogEvent(this);
|
||||
List<DeviceChannel> channels = new ArrayList<>();
|
||||
if (deviceChannels.size() > 1) {
|
||||
// 数据去重
|
||||
Set<String> gbIdSet = new HashSet<>();
|
||||
for (DeviceChannel deviceChannel : deviceChannels) {
|
||||
if (!gbIdSet.contains(deviceChannel.getChannelId())) {
|
||||
gbIdSet.add(deviceChannel.getChannelId());
|
||||
channels.add(deviceChannel);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
channels = deviceChannels;
|
||||
}
|
||||
outEvent.setDeviceChannels(channels);
|
||||
outEvent.setType(type);
|
||||
outEvent.setPlatformId(platformId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) {
|
||||
CatalogEvent outEvent = new CatalogEvent(this);
|
||||
outEvent.setGbStreams(gbStreams);
|
||||
outEvent.setType(type);
|
||||
outEvent.setPlatformId(platformId);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
|
||||
public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) {
|
||||
List<GbStream> gbStreamList = new ArrayList<>();
|
||||
gbStreamList.add(gbStream);
|
||||
catalogEventPublishForStream(platformId, gbStreamList, type);
|
||||
}
|
||||
|
||||
public void recordEndEventPush(RecordInfo recordInfo) {
|
||||
RecordEndEvent outEvent = new RecordEndEvent(this);
|
||||
outEvent.setRecordInfo(recordInfo);
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java
Normal file → Executable file
77
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
Normal file → Executable file
77
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
Normal file → Executable file
@ -1,55 +1,68 @@
|
||||
package com.genersoft.iot.vmp.gb28181.event.alarm;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @description: 报警事件监听
|
||||
* @author: lawrencehj
|
||||
* @data: 2021-01-20
|
||||
* 报警事件监听器.
|
||||
*
|
||||
* @author lawrencehj
|
||||
* @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
|
||||
* @since 2021/01/20
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class AlarmEventListener implements ApplicationListener<AlarmEvent> {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AlarmEventListener.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlarmEventListener.class);
|
||||
|
||||
private static Map<String, SseEmitter> sseEmitters = new Hashtable<>();
|
||||
private static final Map<String, PrintWriter> SSE_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
public void addSseEmitters(String browserId, SseEmitter sseEmitter) {
|
||||
sseEmitters.put(browserId, sseEmitter);
|
||||
public void addSseEmitter(String browserId, PrintWriter writer) {
|
||||
SSE_CACHE.put(browserId, writer);
|
||||
logger.info("SSE 在线数量: {}", SSE_CACHE.size());
|
||||
}
|
||||
|
||||
public void removeSseEmitter(String browserId, PrintWriter writer) {
|
||||
SSE_CACHE.remove(browserId, writer);
|
||||
logger.info("SSE 在线数量: {}", SSE_CACHE.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AlarmEvent event) {
|
||||
public void onApplicationEvent(@NotNull AlarmEvent event) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("设备报警事件触发,deviceId:" + event.getAlarmInfo().getDeviceId() + ", "
|
||||
+ event.getAlarmInfo().getAlarmDescription());
|
||||
logger.debug("设备报警事件触发, deviceId: {}, {}", event.getAlarmInfo().getDeviceId(), event.getAlarmInfo().getAlarmDescription());
|
||||
}
|
||||
String msg = "<strong>设备编码:</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>"
|
||||
+ "<br><strong>报警描述:</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>"
|
||||
+ "<br><strong>报警时间:</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>"
|
||||
+ "<br><strong>报警位置:</strong> <i>" + event.getAlarmInfo().getLongitude() + "</i>"
|
||||
+ ", <i>" + event.getAlarmInfo().getLatitude() + "</i>";
|
||||
|
||||
for (Iterator<Map.Entry<String, SseEmitter>> it = sseEmitters.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, SseEmitter> emitter = it.next();
|
||||
logger.info("推送到SSE连接,浏览器ID: " + emitter.getKey());
|
||||
String msg = "<strong>设备编号:</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>"
|
||||
+ "<br><strong>通道编号:</strong> <i>" + event.getAlarmInfo().getChannelId() + "</i>"
|
||||
+ "<br><strong>报警描述:</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>"
|
||||
+ "<br><strong>报警时间:</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>";
|
||||
|
||||
for (Iterator<Map.Entry<String, PrintWriter>> it = SSE_CACHE.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<String, PrintWriter> response = it.next();
|
||||
logger.info("推送到 SSE 连接, 浏览器 ID: {}", response.getKey());
|
||||
try {
|
||||
emitter.getValue().send(msg);
|
||||
} catch (IOException | IllegalStateException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SSE连接已关闭");
|
||||
PrintWriter writer = response.getValue();
|
||||
|
||||
if (writer.checkError()) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
// 移除已关闭的连接
|
||||
|
||||
String sseMsg = "event:message\n" +
|
||||
"data:" + msg + "\n" +
|
||||
"\n";
|
||||
writer.write(sseMsg);
|
||||
writer.flush();
|
||||
} catch (Exception e) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java
Normal file → Executable file
22
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java
Normal file → Executable file
22
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java
Normal file → Executable file
@ -36,16 +36,17 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
|
||||
public void onApplicationEvent(RecordEndEvent event) {
|
||||
String deviceId = event.getRecordInfo().getDeviceId();
|
||||
String channelId = event.getRecordInfo().getChannelId();
|
||||
String sn = event.getRecordInfo().getSn();
|
||||
int count = event.getRecordInfo().getCount();
|
||||
int sumNum = event.getRecordInfo().getSumNum();
|
||||
logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}/{}条",
|
||||
event.getRecordInfo().getDeviceId(),
|
||||
event.getRecordInfo().getChannelId(), count,sumNum);
|
||||
logger.debug("handlerMap.size => {}", handlerMap.size());
|
||||
if (handlerMap.size() > 0) {
|
||||
String key = deviceId + channelId;
|
||||
if (!handlerMap.isEmpty()) {
|
||||
String key = deviceId + channelId + sn;
|
||||
logger.debug("handlerMap.keys => {}", handlerMap.keySet());
|
||||
RecordEndEventHandler handler = handlerMap.get(deviceId + channelId);
|
||||
RecordEndEventHandler handler = handlerMap.get(deviceId + channelId + sn);
|
||||
logger.debug("handler => {}", handler);
|
||||
if (handler != null){
|
||||
handler.handler(event.getRecordInfo());
|
||||
@ -62,6 +63,9 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
|
||||
scheduleMap.put(key,schedule);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
logger.info("录像查询完成事件触发, 但是订阅为空,取消发送,deviceId:{}, channelId: {}",
|
||||
event.getRecordInfo().getDeviceId(), event.getRecordInfo().getChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,18 +75,18 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
|
||||
* @param channelId
|
||||
* @param recordEndEventHandler
|
||||
*/
|
||||
public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) {
|
||||
logger.debug("RecordEndEventListener addEndEventHandler => deviceId: {}, channelId: {}", device,channelId);
|
||||
handlerMap.put(device + channelId, recordEndEventHandler);
|
||||
public void addEndEventHandler(String device, String channelId, String sn, RecordEndEventHandler recordEndEventHandler) {
|
||||
logger.debug("RecordEndEventListener addEndEventHandler => deviceId: {}, channelId: {}, sn: {}", device,channelId, sn);
|
||||
handlerMap.put(device + channelId + sn, recordEndEventHandler);
|
||||
}
|
||||
/**
|
||||
* 添加
|
||||
* @param device
|
||||
* @param channelId
|
||||
*/
|
||||
public void delEndEventHandler(String device, String channelId) {
|
||||
logger.debug("RecordEndEventListener delEndEventHandler => deviceId: {}, channelId: {}", device,channelId);
|
||||
handlerMap.remove(device + channelId);
|
||||
public void delEndEventHandler(String device, String channelId, String sn) {
|
||||
logger.debug("RecordEndEventListener delEndEventHandler => deviceId: {}, channelId: {}, sn: {}", device,channelId,sn);
|
||||
handlerMap.remove(device + channelId + sn);
|
||||
}
|
||||
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
Normal file → Executable file
13
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
Normal file → Executable file
13
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
Normal file → Executable file
@ -93,7 +93,10 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
}
|
||||
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
|
||||
for (GbStream gbStream : event.getGbStreams()) {
|
||||
if (gbStream.getStreamType().equals("push") && !userSetting.isUsePushingAsStatus()) {
|
||||
if (gbStream != null
|
||||
&& gbStream.getStreamType() != null
|
||||
&& gbStream.getStreamType().equals("push")
|
||||
&& !userSetting.isUsePushingAsStatus()) {
|
||||
continue;
|
||||
}
|
||||
DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
|
||||
@ -145,13 +148,13 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
if (event.getDeviceChannels() != null) {
|
||||
deviceChannelList.addAll(event.getDeviceChannels());
|
||||
}
|
||||
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
|
||||
if (event.getGbStreams() != null && !event.getGbStreams().isEmpty()){
|
||||
for (GbStream gbStream : event.getGbStreams()) {
|
||||
deviceChannelList.add(
|
||||
gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), parentPlatform));
|
||||
}
|
||||
}
|
||||
if (deviceChannelList.size() > 0) {
|
||||
if (!deviceChannelList.isEmpty()) {
|
||||
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
|
||||
@ -160,10 +163,10 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}else if (parentPlatformMap.keySet().size() > 0) {
|
||||
}else if (!parentPlatformMap.keySet().isEmpty()) {
|
||||
for (String gbId : parentPlatformMap.keySet()) {
|
||||
List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
|
||||
if (parentPlatforms != null && parentPlatforms.size() > 0) {
|
||||
if (parentPlatforms != null && !parentPlatforms.isEmpty()) {
|
||||
for (ParentPlatform platform : parentPlatforms) {
|
||||
SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
|
||||
if (subscribeInfo == null) {
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
Normal file → Executable file
2
src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java
Normal file → Executable file
2
src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java
Normal file → Executable file
@ -71,7 +71,7 @@ public class RecordDataCatch {
|
||||
msg.setKey(msgKey);
|
||||
msg.setData(recordInfo);
|
||||
deferredResultHolder.invokeAllResult(msg);
|
||||
recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId());
|
||||
recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId(),recordInfo.getSn());
|
||||
data.remove(key);
|
||||
}
|
||||
}
|
||||
|
6
src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java
Normal file → Executable file
6
src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java
Normal file → Executable file
@ -8,6 +8,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -37,7 +38,8 @@ public class SSRCFactory {
|
||||
|
||||
|
||||
public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
|
||||
String ssrcPrefix = sipConfig.getDomain().substring(3, 8);
|
||||
String sipDomain = sipConfig.getDomain();
|
||||
String ssrcPrefix = sipDomain.length() >= 8 ? sipDomain.substring(3, 8) : sipDomain;
|
||||
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
|
||||
List<String> ssrcList = new ArrayList<>();
|
||||
for (int i = 1; i < MAX_STREAM_COUNT; i++) {
|
||||
@ -118,7 +120,7 @@ public class SSRCFactory {
|
||||
*/
|
||||
public boolean hasMediaServerSSRC(String mediaServerId) {
|
||||
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
|
||||
return redisTemplate.opsForSet().members(redisKey) != null;
|
||||
return Boolean.TRUE.equals(redisTemplate.hasKey(redisKey));
|
||||
}
|
||||
|
||||
}
|
||||
|
316
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
Normal file → Executable file
316
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
Normal file → Executable file
@ -1,139 +1,177 @@
|
||||
package com.genersoft.iot.vmp.gb28181.session;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.utils.JsonUtil;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||
*/
|
||||
@Component
|
||||
public class VideoStreamSessionManager {
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 添加一个点播/回放的事务信息
|
||||
* 后续可以通过流Id/callID
|
||||
* @param deviceId 设备ID
|
||||
* @param channelId 通道ID
|
||||
* @param callId 一次请求的CallID
|
||||
* @param stream 流名称
|
||||
* @param mediaServerId 所使用的流媒体ID
|
||||
* @param response 回复
|
||||
*/
|
||||
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){
|
||||
SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
||||
ssrcTransaction.setDeviceId(deviceId);
|
||||
ssrcTransaction.setChannelId(channelId);
|
||||
ssrcTransaction.setStream(stream);
|
||||
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
|
||||
ssrcTransaction.setCallId(callId);
|
||||
ssrcTransaction.setSsrc(ssrc);
|
||||
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||
ssrcTransaction.setType(type);
|
||||
|
||||
redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
|
||||
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
|
||||
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
deviceId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
callId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(stream)) {
|
||||
stream ="*";
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}
|
||||
|
||||
public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
deviceId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
callId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(stream)) {
|
||||
stream ="*";
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
List<SsrcTransaction> result = new ArrayList<>();
|
||||
for (Object keyObj : scanResult) {
|
||||
result.add((SsrcTransaction)redisTemplate.opsForValue().get(keyObj));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getMediaServerId(String deviceId, String channelId, String stream){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
return ssrcTransaction.getMediaServerId();
|
||||
}
|
||||
|
||||
public String getSSRC(String deviceId, String channelId, String stream){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
return ssrcTransaction.getSsrc();
|
||||
}
|
||||
|
||||
public void remove(String deviceId, String channelId, String stream) {
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return;
|
||||
}
|
||||
redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
|
||||
+ deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
|
||||
}
|
||||
|
||||
|
||||
public List<SsrcTransaction> getAllSsrc() {
|
||||
List<Object> ssrcTransactionKeys = RedisUtil.scan(redisTemplate, String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId()));
|
||||
List<SsrcTransaction> result= new ArrayList<>();
|
||||
for (Object ssrcTransactionKey : ssrcTransactionKeys) {
|
||||
String key = (String) ssrcTransactionKey;
|
||||
SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(redisTemplate, key, SsrcTransaction.class);
|
||||
result.add(ssrcTransaction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.session;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.utils.JsonUtil;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 视频流session管理器,管理视频预览、预览回放的通信句柄
|
||||
*/
|
||||
@Component
|
||||
public class VideoStreamSessionManager {
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 添加一个点播/回放的事务信息
|
||||
* 后续可以通过流Id/callID
|
||||
* @param deviceId 设备ID
|
||||
* @param channelId 通道ID
|
||||
* @param callId 一次请求的CallID
|
||||
* @param stream 流名称
|
||||
* @param mediaServerId 所使用的流媒体ID
|
||||
* @param response 回复
|
||||
*/
|
||||
public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){
|
||||
SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
||||
ssrcTransaction.setDeviceId(deviceId);
|
||||
ssrcTransaction.setChannelId(channelId);
|
||||
ssrcTransaction.setStream(stream);
|
||||
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
|
||||
ssrcTransaction.setCallId(callId);
|
||||
ssrcTransaction.setSsrc(ssrc);
|
||||
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||
ssrcTransaction.setType(type);
|
||||
|
||||
redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
|
||||
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
|
||||
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
deviceId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
callId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(stream)) {
|
||||
stream ="*";
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransactionByCallId(String callId){
|
||||
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
return null;
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_" + callId+ "_*";
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (!scanResult.isEmpty()) {
|
||||
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}else {
|
||||
key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_play_*";
|
||||
scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (Object keyObj : scanResult) {
|
||||
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisTemplate.opsForValue().get(keyObj);
|
||||
if (ssrcTransaction.getSipTransactionInfo() != null &&
|
||||
ssrcTransaction.getSipTransactionInfo().getCallId().equals(callId)) {
|
||||
return ssrcTransaction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
deviceId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
callId ="*";
|
||||
}
|
||||
if (ObjectUtils.isEmpty(stream)) {
|
||||
stream ="*";
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
List<SsrcTransaction> result = new ArrayList<>();
|
||||
for (Object keyObj : scanResult) {
|
||||
result.add((SsrcTransaction)redisTemplate.opsForValue().get(keyObj));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getMediaServerId(String deviceId, String channelId, String stream){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
return ssrcTransaction.getMediaServerId();
|
||||
}
|
||||
|
||||
public String getSSRC(String deviceId, String channelId, String stream){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
if (ssrcTransaction == null) {
|
||||
return null;
|
||||
}
|
||||
return ssrcTransaction.getSsrc();
|
||||
}
|
||||
|
||||
public void remove(String deviceId, String channelId, String stream) {
|
||||
List<SsrcTransaction> ssrcTransactionList = getSsrcTransactionForAll(deviceId, channelId, null, stream);
|
||||
if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (SsrcTransaction ssrcTransaction : ssrcTransactionList) {
|
||||
redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
|
||||
+ deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeByCallId(String deviceId, String channelId, String callId) {
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
|
||||
if (ssrcTransaction == null ) {
|
||||
return;
|
||||
}
|
||||
redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
|
||||
+ deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
|
||||
}
|
||||
|
||||
|
||||
public List<SsrcTransaction> getAllSsrc() {
|
||||
List<Object> ssrcTransactionKeys = RedisUtil.scan(redisTemplate, String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId()));
|
||||
List<SsrcTransaction> result= new ArrayList<>();
|
||||
for (Object ssrcTransactionKey : ssrcTransactionKeys) {
|
||||
String key = (String) ssrcTransactionKey;
|
||||
SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(redisTemplate, key, SsrcTransaction.class);
|
||||
result.add(ssrcTransaction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java
Normal file → Executable file
16
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
Normal file → Executable file
16
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
Normal file → Executable file
@ -12,13 +12,19 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IPlatformService;
|
||||
import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -59,6 +65,8 @@ public class SipRunner implements CommandLineRunner {
|
||||
@Autowired
|
||||
private ISIPCommanderForPlatform commanderForPlatform;
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
List<Device> deviceList = deviceService.getAllOnlineDevice();
|
||||
@ -110,11 +118,17 @@ public class SipRunner implements CommandLineRunner {
|
||||
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
|
||||
ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
|
||||
if (platform != null) {
|
||||
commanderForPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
|
||||
try {
|
||||
commanderForPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
8
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
Normal file → Executable file
8
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
Normal file → Executable file
@ -89,17 +89,17 @@ public class CatalogSubscribeTask implements ISubscribeTask {
|
||||
ResponseEvent event = (ResponseEvent) eventResult.event;
|
||||
if (event.getResponse().getRawContent() != null) {
|
||||
// 成功
|
||||
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
|
||||
logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
|
||||
}else {
|
||||
// 成功
|
||||
logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
|
||||
logger.info("[取消目录订阅]成功: {}", device.getDeviceId());
|
||||
}
|
||||
},eventResult -> {
|
||||
// 失败
|
||||
logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
logger.warn("[取消目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 取消目录订阅订阅: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 取消目录订阅: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
Normal file → Executable file
@ -66,17 +66,17 @@ public class SIPSender {
|
||||
// 添加错误订阅
|
||||
if (errorEvent != null) {
|
||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
|
||||
errorEvent.response(eventResult);
|
||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
||||
errorEvent.response(eventResult);
|
||||
}));
|
||||
}
|
||||
// 添加订阅
|
||||
if (okEvent != null) {
|
||||
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
|
||||
okEvent.response(eventResult);
|
||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
||||
okEvent.response(eventResult);
|
||||
});
|
||||
}
|
||||
if ("TCP".equals(transport)) {
|
||||
|
320
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
Normal file → Executable file
320
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
Normal file → Executable file
@ -1,160 +1,160 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||
|
||||
import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @description: 异步请求处理
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午7:59:05
|
||||
*/
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
@Component
|
||||
public class DeferredResultHolder {
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
|
||||
|
||||
public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
|
||||
|
||||
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
|
||||
|
||||
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
|
||||
|
||||
public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
|
||||
|
||||
public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK";
|
||||
|
||||
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
|
||||
|
||||
public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY";
|
||||
|
||||
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
||||
|
||||
public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL";
|
||||
|
||||
public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION";
|
||||
|
||||
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
|
||||
|
||||
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
|
||||
|
||||
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
|
||||
|
||||
public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP";
|
||||
|
||||
private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public void put(String key, String id, DeferredResultEx result) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
deferredResultMap = new ConcurrentHashMap<>();
|
||||
map.put(key, deferredResultMap);
|
||||
}
|
||||
deferredResultMap.put(id, result);
|
||||
}
|
||||
|
||||
public void put(String key, String id, DeferredResult result) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
deferredResultMap = new ConcurrentHashMap<>();
|
||||
map.put(key, deferredResultMap);
|
||||
}
|
||||
deferredResultMap.put(id, new DeferredResultEx(result));
|
||||
}
|
||||
|
||||
public DeferredResultEx get(String key, String id) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null || ObjectUtils.isEmpty(id)) {
|
||||
return null;
|
||||
}
|
||||
return deferredResultMap.get(id);
|
||||
}
|
||||
|
||||
public Collection<DeferredResultEx> getAllByKey(String key) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
return null;
|
||||
}
|
||||
return deferredResultMap.values();
|
||||
}
|
||||
|
||||
public boolean exist(String key, String id){
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (id == null) {
|
||||
return deferredResultMap != null;
|
||||
}else {
|
||||
return deferredResultMap != null && deferredResultMap.get(id) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放单个请求
|
||||
* @param msg
|
||||
*/
|
||||
public void invokeResult(RequestMessage msg) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
DeferredResultEx result = deferredResultMap.get(msg.getId());
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
result.getDeferredResult().setResult(msg.getData());
|
||||
deferredResultMap.remove(msg.getId());
|
||||
if (deferredResultMap.size() == 0) {
|
||||
map.remove(msg.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放所有的请求
|
||||
* @param msg
|
||||
*/
|
||||
public void invokeAllResult(RequestMessage msg) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> ids = deferredResultMap.keySet();
|
||||
for (String id : ids) {
|
||||
DeferredResultEx result = deferredResultMap.get(id);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
if (result.getFilter() != null) {
|
||||
Object handler = result.getFilter().handler(msg.getData());
|
||||
result.getDeferredResult().setResult(handler);
|
||||
}else {
|
||||
result.getDeferredResult().setResult(msg.getData());
|
||||
}
|
||||
|
||||
}
|
||||
map.remove(msg.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||
|
||||
import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @description: 异步请求处理
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午7:59:05
|
||||
*/
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
@Component
|
||||
public class DeferredResultHolder {
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL";
|
||||
|
||||
public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG";
|
||||
|
||||
public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD";
|
||||
|
||||
public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG";
|
||||
|
||||
public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO";
|
||||
|
||||
public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
|
||||
|
||||
public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK";
|
||||
|
||||
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
|
||||
|
||||
public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY";
|
||||
|
||||
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
||||
|
||||
public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL";
|
||||
|
||||
public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION";
|
||||
|
||||
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
|
||||
|
||||
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
|
||||
|
||||
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
|
||||
|
||||
public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP";
|
||||
|
||||
private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public void put(String key, String id, DeferredResultEx result) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
deferredResultMap = new ConcurrentHashMap<>();
|
||||
map.put(key, deferredResultMap);
|
||||
}
|
||||
deferredResultMap.put(id, result);
|
||||
}
|
||||
|
||||
public void put(String key, String id, DeferredResult result) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
deferredResultMap = new ConcurrentHashMap<>();
|
||||
map.put(key, deferredResultMap);
|
||||
}
|
||||
deferredResultMap.put(id, new DeferredResultEx(result));
|
||||
}
|
||||
|
||||
public DeferredResultEx get(String key, String id) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null || ObjectUtils.isEmpty(id)) {
|
||||
return null;
|
||||
}
|
||||
return deferredResultMap.get(id);
|
||||
}
|
||||
|
||||
public Collection<DeferredResultEx> getAllByKey(String key) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (deferredResultMap == null) {
|
||||
return null;
|
||||
}
|
||||
return deferredResultMap.values();
|
||||
}
|
||||
|
||||
public boolean exist(String key, String id){
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(key);
|
||||
if (id == null) {
|
||||
return deferredResultMap != null;
|
||||
}else {
|
||||
return deferredResultMap != null && deferredResultMap.get(id) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放单个请求
|
||||
* @param msg
|
||||
*/
|
||||
public void invokeResult(RequestMessage msg) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
DeferredResultEx result = deferredResultMap.get(msg.getId());
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
result.getDeferredResult().setResult(msg.getData());
|
||||
deferredResultMap.remove(msg.getId());
|
||||
if (deferredResultMap.size() == 0) {
|
||||
map.remove(msg.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放所有的请求
|
||||
* @param msg
|
||||
*/
|
||||
public void invokeAllResult(RequestMessage msg) {
|
||||
Map<String, DeferredResultEx> deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
deferredResultMap = map.get(msg.getKey());
|
||||
if (deferredResultMap == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> ids = deferredResultMap.keySet();
|
||||
for (String id : ids) {
|
||||
DeferredResultEx result = deferredResultMap.get(id);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
if (result.getFilter() != null) {
|
||||
Object handler = result.getFilter().handler(msg.getData());
|
||||
result.getDeferredResult().setResult(handler);
|
||||
}else {
|
||||
result.getDeferredResult().setResult(msg.getData());
|
||||
}
|
||||
|
||||
}
|
||||
map.remove(msg.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
78
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
Normal file → Executable file
78
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
Normal file → Executable file
@ -1,39 +1,39 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||
|
||||
/**
|
||||
* @description: 请求信息定义
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午1:09:18
|
||||
*/
|
||||
public class RequestMessage {
|
||||
|
||||
private String id;
|
||||
|
||||
private String key;
|
||||
|
||||
private Object data;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
||||
|
||||
/**
|
||||
* @description: 请求信息定义
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午1:09:18
|
||||
*/
|
||||
public class RequestMessage {
|
||||
|
||||
private String id;
|
||||
|
||||
private String key;
|
||||
|
||||
private Object data;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
737
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
Normal file → Executable file
737
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
Normal file → Executable file
@ -1,364 +1,373 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月3日 下午9:16:34
|
||||
*/
|
||||
public interface ISIPCommander {
|
||||
|
||||
/**
|
||||
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
*/
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台方向放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param moveSpeed 镜头移动速度
|
||||
*/
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制,使用配置文件中的默认镜头缩放速度
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台控制,支持方向与缩放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
* @param moveSpeed 镜头移动速度
|
||||
* @param zoomSpeed 镜头缩放速度
|
||||
*/
|
||||
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param cmdCode 指令码
|
||||
* @param parameter1 数据1
|
||||
* @param parameter2 数据2
|
||||
* @param combineCode2 组合码2
|
||||
*/
|
||||
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制指令(用于转发上级指令)
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求预览视频流
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求历史媒体下载
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param downloadSpeed 下载倍速参数
|
||||
*/
|
||||
void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent,
|
||||
SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
*/
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
|
||||
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
|
||||
|
||||
/**
|
||||
* 回放暂停
|
||||
*/
|
||||
void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放恢复
|
||||
*/
|
||||
void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放拖动播放
|
||||
*/
|
||||
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放倍速播放
|
||||
*/
|
||||
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放控制
|
||||
* @param device
|
||||
* @param streamInfo
|
||||
* @param content
|
||||
*/
|
||||
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void audioBroadcastCmd(Device device,String channelId);
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 音视频录像控制
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||
*/
|
||||
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 远程启动控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警复位命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param alarmMethod 报警方式(可选)
|
||||
* @param alarmType 报警类型(可选)
|
||||
*/
|
||||
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 看守位控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道id,非通道则是设备本身
|
||||
* @param enabled 看守位使能:1 = 开启,0 = 关闭
|
||||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 设备配置命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void deviceConfigCmd(Device device);
|
||||
|
||||
/**
|
||||
* 设备配置命令:basicParam
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param name 设备/通道名称(可选)
|
||||
* @param expiration 注册过期时间(可选)
|
||||
* @param heartBeatInterval 心跳间隔时间(可选)
|
||||
* @param heartBeatCount 心跳超时次数(可选)
|
||||
*/
|
||||
void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备状态
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @return
|
||||
*/
|
||||
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询目录列表
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询录像信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param sn
|
||||
*/
|
||||
void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询报警信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethod 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备配置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param configType 配置类型:
|
||||
*/
|
||||
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备预置位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询移动设备位置数据
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅移动位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅报警信息
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅过期时间(0 = 取消订阅)
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅目录信息
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 拉框控制命令
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 通道id
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待
|
||||
* @param device 设备
|
||||
* @param deviceAlarm 报警信息信息
|
||||
* @return
|
||||
*/
|
||||
void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月3日 下午9:16:34
|
||||
*/
|
||||
public interface ISIPCommander {
|
||||
|
||||
/**
|
||||
* 云台方向放控制,使用配置文件中的默认镜头移动速度
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
*/
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台方向放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param moveSpeed 镜头移动速度
|
||||
*/
|
||||
void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制,使用配置文件中的默认镜头缩放速度
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台缩放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
*/
|
||||
void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 云台控制,支持方向与缩放控制
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
|
||||
* @param upDown 镜头上移下移 0:停止 1:上移 2:下移
|
||||
* @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
|
||||
* @param moveSpeed 镜头移动速度
|
||||
* @param zoomSpeed 镜头缩放速度
|
||||
*/
|
||||
void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param cmdCode 指令码
|
||||
* @param parameter1 数据1
|
||||
* @param parameter2 数据2
|
||||
* @param combineCode2 组合码2
|
||||
*/
|
||||
void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 前端控制指令(用于转发上级指令)
|
||||
* @param device 控制设备
|
||||
* @param channelId 预览通道
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求预览视频流
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
Function<String, Void> ignoreCallBack,
|
||||
Function<SIPResponse, Void> inviteCallBack,
|
||||
ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,
|
||||
Function<String, Void> ignoreCallBack,
|
||||
Function<SIPResponse, Void> inviteCallBack,
|
||||
ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求历史媒体下载
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param downloadSpeed 下载倍速参数
|
||||
*/
|
||||
void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
String startTime, String endTime, int downloadSpeed, Function<String, Void> ignoreCallBack, Function<SIPResponse, Void> inviteCallBack, ZlmHttpHookSubscribe.Event hookEvent,
|
||||
SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
*/
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
|
||||
|
||||
|
||||
void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
|
||||
|
||||
/**
|
||||
* 回放暂停
|
||||
*/
|
||||
void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放恢复
|
||||
*/
|
||||
void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放拖动播放
|
||||
*/
|
||||
void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放倍速播放
|
||||
*/
|
||||
void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
/**
|
||||
* 回放控制
|
||||
* @param device
|
||||
* @param streamInfo
|
||||
* @param content
|
||||
*/
|
||||
void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void audioBroadcastCmd(Device device,String channelId);
|
||||
|
||||
/**
|
||||
* 语音广播
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 音视频录像控制
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param recordCmdStr 录像命令:Record / StopRecord
|
||||
*/
|
||||
void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 远程启动控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警布防/撤防命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 报警复位命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param alarmMethod 报警方式(可选)
|
||||
* @param alarmType 报警类型(可选)
|
||||
*/
|
||||
void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 看守位控制命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道id,非通道则是设备本身
|
||||
* @param enabled 看守位使能:1 = 开启,0 = 关闭
|
||||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 设备配置命令
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void deviceConfigCmd(Device device);
|
||||
|
||||
/**
|
||||
* 设备配置命令:basicParam
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param name 设备/通道名称(可选)
|
||||
* @param expiration 注册过期时间(可选)
|
||||
* @param heartBeatInterval 心跳间隔时间(可选)
|
||||
* @param heartBeatCount 心跳超时次数(可选)
|
||||
*/
|
||||
void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备状态
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @return
|
||||
*/
|
||||
void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询目录列表
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询录像信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param sn
|
||||
*/
|
||||
void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询报警信息
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmMethod 报警方式条件(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
|
||||
String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备配置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 通道编码(可选)
|
||||
* @param configType 配置类型:
|
||||
*/
|
||||
void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询设备预置位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询移动设备位置数据
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅移动位置
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅报警信息
|
||||
* @param device 视频设备
|
||||
* @param expires 订阅过期时间(0 = 取消订阅)
|
||||
* @param startPriority 报警起始级别(可选)
|
||||
* @param endPriority 报警终止级别(可选)
|
||||
* @param alarmType 报警类型
|
||||
* @param startTime 报警发生起始时间(可选)
|
||||
* @param endTime 报警发生终止时间(可选)
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 订阅、取消订阅目录信息
|
||||
* @param device 视频设备
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 拉框控制命令
|
||||
*
|
||||
* @param device 控制设备
|
||||
* @param channelId 通道id
|
||||
* @param cmdString 前端控制指令串
|
||||
*/
|
||||
void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待
|
||||
* @param device 设备
|
||||
* @param deviceAlarm 报警信息信息
|
||||
* @return
|
||||
*/
|
||||
void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
}
|
||||
|
2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
Normal file → Executable file
2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
Normal file → Executable file
@ -20,6 +20,8 @@ public interface ISIPCommanderForPlatform {
|
||||
void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
|
||||
void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
|
||||
|
||||
/**
|
||||
|
6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
Normal file → Executable file
6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
Normal file → Executable file
@ -227,11 +227,11 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
|
||||
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse().getToTag());
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getResponse() != null ? subscribeInfo.getResponse().getToTag(): subscribeInfo.getSimulatedToTag());
|
||||
// to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest().getFromTag());
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, subscribeInfo.getRequest() != null ?subscribeInfo.getRequest().getFromTag(): subscribeInfo.getSimulatedFromTag());
|
||||
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
@ -241,7 +241,7 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
// 设置编码, 防止中文乱码
|
||||
messageFactory.setDefaultContentEncodingCharset("gb2312");
|
||||
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest().getCallIdHeader().getCallId());
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(subscribeInfo.getRequest() != null ? subscribeInfo.getRequest().getCallIdHeader().getCallId(): subscribeInfo.getSimulatedCallId());
|
||||
|
||||
request = (SIPRequest) messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
638
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
Normal file → Executable file
638
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
Normal file → Executable file
@ -1,318 +1,320 @@
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.PeerUnavailableException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.SipFactory;
|
||||
import javax.sip.address.Address;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月6日 上午9:29:02
|
||||
*/
|
||||
@Component
|
||||
public class SIPRequestHeaderProvider {
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private SipLayer sipLayer;
|
||||
|
||||
@Autowired
|
||||
private GitUtil gitUtil;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private VideoStreamSessionManager streamSession;
|
||||
|
||||
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
// from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
|
||||
// to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag);
|
||||
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
// ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
|
||||
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
//via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
// Subject
|
||||
SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
|
||||
request.addHeader(subjectHeader);
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
// Subject
|
||||
SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
|
||||
request.addHeader(subjectHeader);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(),
|
||||
device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
// from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
|
||||
// to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
|
||||
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
// ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE);
|
||||
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
// Expires
|
||||
ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires);
|
||||
request.addHeader(expireHeader);
|
||||
|
||||
// Event
|
||||
EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event);
|
||||
|
||||
int random = (int) Math.floor(Math.random() * 10000);
|
||||
eventHeader.setEventId(random + "");
|
||||
request.addHeader(eventHeader);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo)
|
||||
throws SipException, ParseException, InvalidArgumentException {
|
||||
if (device == null || transactionInfo == null) {
|
||||
return null;
|
||||
}
|
||||
SIPRequest request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
if (content != null) {
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application",
|
||||
"MANSRTSP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createAckRequest(String localIp, SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
|
||||
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
|
||||
|
||||
Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.PeerUnavailableException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.SipFactory;
|
||||
import javax.sip.address.Address;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @description:摄像头命令request创造器 TODO 冗余代码太多待优化
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月6日 上午9:29:02
|
||||
*/
|
||||
@Component
|
||||
public class SIPRequestHeaderProvider {
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private SipLayer sipLayer;
|
||||
|
||||
@Autowired
|
||||
private GitUtil gitUtil;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private VideoStreamSessionManager streamSession;
|
||||
|
||||
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
// from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag);
|
||||
// to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, toTag);
|
||||
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
// ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.MESSAGE);
|
||||
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
//via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
// Subject
|
||||
SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
|
||||
request.addHeader(subjectHeader);
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), viaTag);
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress,null);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
// Subject
|
||||
SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getId(), 0));
|
||||
request.addHeader(subjectHeader);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
// SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(),device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createSubscribeRequest(Device device, String content, SIPRequest requestOld, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
Request request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(),
|
||||
device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeader.setRPort();
|
||||
viaHeaders.add(viaHeader);
|
||||
// from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, requestOld == null ? SipUtils.getNewFromTag() :requestOld.getFromTag());
|
||||
// to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, requestOld == null ? null :requestOld.getToTag());
|
||||
|
||||
// Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
// ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.SUBSCRIBE);
|
||||
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.SUBSCRIBE, callIdHeader, cSeqHeader, fromHeader,
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
// Expires
|
||||
ExpiresHeader expireHeader = SipFactory.getInstance().createHeaderFactory().createExpiresHeader(expires);
|
||||
request.addHeader(expireHeader);
|
||||
|
||||
// Event
|
||||
EventHeader eventHeader = SipFactory.getInstance().createHeaderFactory().createEventHeader(event);
|
||||
|
||||
int random = (int) Math.floor(Math.random() * 10000);
|
||||
eventHeader.setEventId(random + "");
|
||||
request.addHeader(eventHeader);
|
||||
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo)
|
||||
throws SipException, ParseException, InvalidArgumentException {
|
||||
if (device == null || transactionInfo == null) {
|
||||
return null;
|
||||
}
|
||||
SIPRequest request = null;
|
||||
//请求行
|
||||
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
|
||||
Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
|
||||
ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
|
||||
CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
|
||||
request = (SIPRequest)SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
if (content != null) {
|
||||
ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("Application",
|
||||
"MANSRTSP");
|
||||
request.setContent(content, contentTypeHeader);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request createAckRequest(String localIp, SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||
|
||||
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
|
||||
viaHeaders.add(viaHeader);
|
||||
|
||||
//Forwards
|
||||
MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
|
||||
|
||||
//ceq
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
|
||||
|
||||
Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
2890
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
Normal file → Executable file
2890
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
92
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
Normal file → Executable file
92
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
Normal file → Executable file
@ -19,7 +19,8 @@ import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import gov.nist.javax.sip.message.MessageFactoryImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.lang.Nullable;
|
||||
@ -36,10 +37,12 @@ import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@DependsOn("sipLayer")
|
||||
public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
|
||||
|
||||
@Autowired
|
||||
private SIPRequestHeaderPlarformProvider headerProviderPlatformProvider;
|
||||
|
||||
@ -109,14 +112,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
toTag, callIdHeader, isRegister? parentPlatform.getExpires() : 0);
|
||||
// 将 callid 写入缓存, 等注册成功可以更新状态
|
||||
String callIdFromHeader = callIdHeader.getCallId();
|
||||
PlatformRegisterInfo instance = PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister);
|
||||
log.info("callIdFromHeader {}",callIdFromHeader);
|
||||
log.info("PlatformRegisterInfo {}",instance);
|
||||
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, instance);
|
||||
redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
|
||||
|
||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{
|
||||
if (event != null) {
|
||||
log.info("向上级平台 [ {} ] 注册发生错误: {} ",
|
||||
logger.info("向上级平台 [ {} ] 注册发生错误: {} ",
|
||||
parentPlatform.getServerGBId(),
|
||||
event.msg);
|
||||
}
|
||||
@ -148,13 +148,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
|
||||
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(
|
||||
parentPlatform,
|
||||
keepaliveXml.toString(),
|
||||
SipUtils.getNewFromTag(),
|
||||
SipUtils.getNewViaTag(),
|
||||
callIdHeader);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(
|
||||
parentPlatform,
|
||||
keepaliveXml.toString(),
|
||||
SipUtils.getNewFromTag(),
|
||||
SipUtils.getNewViaTag(),
|
||||
callIdHeader);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, errorEvent, okEvent);
|
||||
return callIdHeader.getCallId();
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}else {
|
||||
if (channel.getChannelId().length() != 20) {
|
||||
catalogXml.append("</Item>\r\n");
|
||||
log.warn("[编号长度异常] {} 长度错误,请使用20位长度的国标编号,当前长度:{}", channel.getChannelId(), channel.getChannelId().length());
|
||||
logger.warn("[编号长度异常] {} 长度错误,请使用20位长度的国标编号,当前长度:{}", channel.getChannelId(), channel.getChannelId().length());
|
||||
catalogXml.append("</Item>\r\n");
|
||||
continue;
|
||||
}
|
||||
@ -383,9 +383,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
String callId = request.getCallIdHeader().getCallId();
|
||||
|
||||
log.info("[命令发送] 国标级联{} 目录查询回复: 共{}条,已发送{}条", parentPlatform.getServerGBId(),
|
||||
logger.info("[命令发送] 国标级联{} 目录查询回复: 共{}条,已发送{}条", parentPlatform.getServerGBId(),
|
||||
channels.size(), Math.min(index + parentPlatform.getCatalogGroup(), channels.size()));
|
||||
log.debug(catalogXml);
|
||||
logger.debug(catalogXml);
|
||||
if (sendAfterResponse) {
|
||||
// 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。
|
||||
dynamicTask.startDelay(timeoutTaskKey, ()->{
|
||||
@ -394,11 +394,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
try {
|
||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
}
|
||||
}, 3000);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
|
||||
log.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
||||
logger.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
||||
dynamicTask.stop(timeoutTaskKey);
|
||||
}, eventResult -> {
|
||||
dynamicTask.stop(timeoutTaskKey);
|
||||
@ -406,12 +406,12 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
try {
|
||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, true);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
}else {
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, eventResult -> {
|
||||
log.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
||||
logger.error("[目录推送失败] 国标级联 platform : {}, code: {}, msg: {}, 停止发送", parentPlatform.getServerGBId(), eventResult.statusCode, eventResult.msg);
|
||||
dynamicTask.stop(timeoutTaskKey);
|
||||
}, null);
|
||||
dynamicTask.startDelay(timeoutTaskKey, ()->{
|
||||
@ -419,7 +419,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
try {
|
||||
sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext, false);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
|
||||
}
|
||||
}, 30);
|
||||
}
|
||||
@ -498,8 +498,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
if (parentPlatform == null) {
|
||||
return;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
|
||||
}
|
||||
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
@ -518,7 +518,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
.append("</Notify>\r\n");
|
||||
|
||||
sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
|
||||
log.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, null);
|
||||
|
||||
}
|
||||
@ -528,7 +528,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
if (parentPlatform == null) {
|
||||
return;
|
||||
}
|
||||
log.info("[发送报警通知]平台: {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
|
||||
logger.info("[发送报警通知]平台: {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
|
||||
deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm));
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer deviceStatusXml = new StringBuffer(600);
|
||||
@ -557,7 +557,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
@Override
|
||||
public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
|
||||
if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
|
||||
if (parentPlatform == null || deviceChannels == null || deviceChannels.isEmpty() || subscribeInfo == null) {
|
||||
return;
|
||||
}
|
||||
if (index == null) {
|
||||
@ -575,15 +575,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
|
||||
deviceChannels.size(), type, subscribeInfo);
|
||||
logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
log.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, (eventResult -> {
|
||||
try {
|
||||
sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
|
||||
finalIndex + parentPlatform.getCatalogGroup());
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
log.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
}
|
||||
}));
|
||||
}
|
||||
@ -598,7 +599,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
|
||||
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest, errorEvent, okEvent);
|
||||
}
|
||||
|
||||
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
|
||||
@ -610,9 +611,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
.append("<CmdType>Catalog</CmdType>\r\n")
|
||||
.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
|
||||
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
|
||||
.append("<SumNum>1</SumNum>\r\n")
|
||||
.append("<SumNum>"+ sumNum +"</SumNum>\r\n")
|
||||
.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
|
||||
if (channels.size() > 0) {
|
||||
if (!channels.isEmpty()) {
|
||||
for (DeviceChannel channel : channels) {
|
||||
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
|
||||
channel.setParentId(parentPlatform.getDeviceGBId());
|
||||
@ -663,7 +664,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|| deviceChannels == null
|
||||
|| deviceChannels.size() == 0
|
||||
|| subscribeInfo == null) {
|
||||
log.warn("[缺少必要参数]");
|
||||
logger.warn("[缺少必要参数]");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -679,17 +680,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}else {
|
||||
channels = deviceChannels.subList(index, deviceChannels.size());
|
||||
}
|
||||
logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
log.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, eventResult -> {
|
||||
try {
|
||||
sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
|
||||
finalIndex + parentPlatform.getCatalogGroup());
|
||||
} catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
|
||||
IllegalAccessException e) {
|
||||
log.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -722,17 +724,17 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
@Override
|
||||
public void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException {
|
||||
log.debug("deviceChannel => {}, parentPlatform => {}, fromTag => {}, recordInfo => {}", deviceChannel, parentPlatform, fromTag, recordInfo);
|
||||
if ( parentPlatform ==null) {
|
||||
return ;
|
||||
}
|
||||
logger.info("[国标级联] 发送录像数据通道: {}", recordInfo.getChannelId());
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer recordXml = new StringBuffer(600);
|
||||
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
|
||||
.append("<Response>\r\n")
|
||||
.append("<CmdType>RecordInfo</CmdType>\r\n")
|
||||
.append("<SN>" +recordInfo.getSn() + "</SN>\r\n")
|
||||
.append("<DeviceID>" + recordInfo.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
|
||||
if (recordInfo.getRecordList() == null ) {
|
||||
recordXml.append("<RecordList Num=\"0\">\r\n");
|
||||
@ -742,7 +744,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
for (RecordItem recordItem : recordInfo.getRecordList()) {
|
||||
recordXml.append("<Item>\r\n");
|
||||
if (deviceChannel != null) {
|
||||
recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n")
|
||||
recordXml.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<Name>" + recordItem.getName() + "</Name>\r\n")
|
||||
.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n")
|
||||
.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n")
|
||||
@ -762,12 +764,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
recordXml.append("</RecordList>\r\n")
|
||||
.append("</Response>\r\n");
|
||||
|
||||
logger.info("[国标级联] 发送录像数据通道:{}, 内容: {}", recordInfo.getChannelId(), recordXml);
|
||||
// callid
|
||||
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
|
||||
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, eventResult -> {
|
||||
logger.info("[国标级联] 发送录像数据通道:{}, 发送成功", recordInfo.getChannelId());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -809,14 +813,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
@Override
|
||||
public void streamByeCmd(ParentPlatform parentPlatform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
|
||||
if (sendRtpItem == null ) {
|
||||
log.info("[向上级发送BYE], sendRtpItem 为NULL");
|
||||
logger.info("[向上级发送BYE], sendRtpItem 为NULL");
|
||||
return;
|
||||
}
|
||||
if (parentPlatform == null) {
|
||||
log.info("[向上级发送BYE], platform 为NULL");
|
||||
logger.info("[向上级发送BYE], platform 为NULL");
|
||||
return;
|
||||
}
|
||||
log.info("[向上级发送BYE], {}/{}", parentPlatform.getServerGBId(), sendRtpItem.getChannelId());
|
||||
logger.info("[向上级发送BYE], {}/{}", parentPlatform.getServerGBId(), sendRtpItem.getChannelId());
|
||||
String mediaServerId = sendRtpItem.getMediaServerId();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem != null) {
|
||||
@ -825,7 +829,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(parentPlatform, sendRtpItem);
|
||||
if (byeRequest == null) {
|
||||
log.warn("[向上级发送bye]:无法创建 byeRequest");
|
||||
logger.warn("[向上级发送bye]:无法创建 byeRequest");
|
||||
}
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(),byeRequest);
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java
Normal file → Executable file
8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
Normal file → Executable file
8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
Normal file → Executable file
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@ -196,15 +197,14 @@ public abstract class SIPRequestProcessorParent {
|
||||
result.add(rawContent[i]);
|
||||
}
|
||||
}
|
||||
Byte[] bytes = new Byte[0];
|
||||
byte[] bytesResult = ArrayUtils.toPrimitive(result.toArray(bytes));
|
||||
byte[] bytesResult = Bytes.toArray(result);
|
||||
|
||||
Document xml;
|
||||
try {
|
||||
xml = reader.read(new ByteArrayInputStream(bytesResult));
|
||||
}catch (DocumentException e) {
|
||||
logger.warn("[xml解析异常]: 愿文如下: \r\n{}", new String(bytesResult));
|
||||
logger.warn("[xml解析异常]: 愿文如下: 尝试兼容性处理");
|
||||
logger.warn("[xml解析异常]: 原文如下: \r\n{}", new String(bytesResult));
|
||||
logger.warn("[xml解析异常]: 原文如下: 尝试兼容性处理");
|
||||
String[] xmlLineArray = new String(bytesResult).split("\\r?\\n");
|
||||
|
||||
// 兼容海康的address字段带有<破换xml结构导致无法解析xml的问题
|
||||
|
@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
@ -16,15 +17,20 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.ZlmPublishHookService;
|
||||
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
|
||||
import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.github.rholder.retry.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
@ -38,6 +44,11 @@ import javax.sip.header.ToHeader;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* SIP命令类型: ACK请求
|
||||
@ -90,10 +101,21 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
@Autowired
|
||||
private RedisGbPlayMsgListener redisGbPlayMsgListener;
|
||||
|
||||
@Autowired
|
||||
private SipSubscribe sipSubscribe;
|
||||
|
||||
/**
|
||||
@Autowired
|
||||
private ZlmPublishHookService zlmPublishHookService;
|
||||
|
||||
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
@Qualifier("taskExecutor")
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
/**
|
||||
* 处理 ACK请求
|
||||
*
|
||||
*
|
||||
* @param evt
|
||||
*/
|
||||
@Override
|
||||
@ -116,6 +138,24 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
logger.info("收到ACK,rtp/{} TCP主动方式后续处理", sendRtpItem.getStreamId());
|
||||
return;
|
||||
}
|
||||
|
||||
taskExecutor.execute(()->{
|
||||
long retry = 50;
|
||||
while (retry > 0){
|
||||
SipSubscribe.Event platformAckSubscribe = sipSubscribe.getOkSubscribe("ACK_" + callIdHeader.getCallId());
|
||||
if(platformAckSubscribe != null) {
|
||||
platformAckSubscribe.response(null);
|
||||
break;
|
||||
}
|
||||
retry -=1;
|
||||
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, 协议:{}",
|
||||
@ -141,19 +181,60 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
// 开启rtcp保活
|
||||
param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0");
|
||||
}
|
||||
logger.debug("mediaInfo {}", mediaInfo==null?"null":mediaInfo);
|
||||
if (mediaInfo == null) {
|
||||
RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
|
||||
sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(),
|
||||
sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
|
||||
sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio());
|
||||
logger.debug("sendRtpItem {} {}", JSONObject.toJSONString(sendRtpItem), JSONObject.toJSONString(param));
|
||||
redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{
|
||||
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
|
||||
});
|
||||
}else {
|
||||
JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param);
|
||||
if (startSendRtpStreamResult != null) {
|
||||
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader);
|
||||
}
|
||||
logger.debug("sendRtpItem {} {}", JSONObject.toJSONString(sendRtpItem), JSONObject.toJSONString(param));
|
||||
|
||||
logger.debug("zlmPublishHookService.getHandler(sendRtpItem.getApp()) {} put {}",zlmPublishHookService.getHandler(sendRtpItem.getApp()), sendRtpItem.getStreamId());
|
||||
zlmPublishHookService.getHandler(sendRtpItem.getApp()).put(sendRtpItem.getStreamId(),()->{
|
||||
taskExecutor.submit(()->{
|
||||
JSONObject startSendRtpStreamResult;
|
||||
AtomicReference<String> failMag = new AtomicReference<>("");
|
||||
Retryer<JSONObject> retryer = RetryerBuilder.<JSONObject>newBuilder()
|
||||
.retryIfResult(resp -> {
|
||||
if(resp != null){
|
||||
if(resp.getInteger("code") != 0){
|
||||
String msg = resp.getString("msg");
|
||||
if (!msg.equalsIgnoreCase(failMag.get())){
|
||||
failMag.set(msg);
|
||||
if (!StringUtils.containsIgnoreCase(msg, "can not find the source stream")) {
|
||||
logger.debug("rtp转推失败 {} {}, {}, {}", msg, channelId, mediaInfo, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resp == null || resp.getInteger("code") != 0;
|
||||
})
|
||||
.retryIfException()
|
||||
.retryIfRuntimeException()
|
||||
// 重试间隔
|
||||
.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.MILLISECONDS))
|
||||
// 重试次数
|
||||
.withStopStrategy(StopStrategies.stopAfterAttempt(10 * 1000))
|
||||
.build();
|
||||
try {
|
||||
startSendRtpStreamResult = retryer.call(() -> zlmServerFactory.startSendRtpStream(mediaInfo, param));
|
||||
logger.info("rtp转推成功 {} {} {}", channelId, mediaInfo, param);
|
||||
} catch (ExecutionException | RetryException e) {
|
||||
logger.error("rtp转推失败 {} {} {} => {}, {}", channelId, mediaInfo, param, failMag.get(), e.getMessage());
|
||||
startSendRtpStreamResult = null;
|
||||
}
|
||||
startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader);
|
||||
});
|
||||
});
|
||||
|
||||
scheduledExecutorService.schedule(()->{
|
||||
zlmPublishHookService.getHandler(sendRtpItem.getApp()).remove(sendRtpItem.getStreamId());
|
||||
}, 1, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
|
||||
|
11
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
Normal file → Executable file
11
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
Normal file → Executable file
@ -116,6 +116,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
|
||||
callIdHeader.getCallId(), null);
|
||||
zlmServerFactory.stopSendRtpStream(mediaInfo, param);
|
||||
if (userSetting.getUseCustomSsrcForParentInvite()) {
|
||||
mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());
|
||||
}
|
||||
if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
|
||||
ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
|
||||
if (platform != null) {
|
||||
@ -132,7 +135,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
|
||||
if (totalReaderCount <= 0) {
|
||||
logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
|
||||
if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
|
||||
// if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
|
||||
Device device = deviceService.getDevice(sendRtpItem.getDeviceId());
|
||||
if (device == null) {
|
||||
logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
|
||||
@ -144,12 +147,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
SsrcTransactionNotFoundException e) {
|
||||
logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
}else {
|
||||
|
||||
// 可能是设备发送的停止
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId());
|
||||
if (ssrcTransaction == null) {
|
||||
return;
|
||||
}
|
||||
@ -178,7 +181,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
if (mediaServerItem != null) {
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc());
|
||||
}
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getStream());
|
||||
streamSession.removeByCallId(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getCallId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java
Normal file → Executable file
0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java
Normal file → Executable file
290
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
Normal file → Executable file
290
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
Normal file → Executable file
@ -2,13 +2,19 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
@ -18,10 +24,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.*;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||
import com.genersoft.iot.vmp.service.IStreamPushService;
|
||||
import com.genersoft.iot.vmp.service.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
|
||||
@ -31,7 +34,6 @@ import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.utils.JsonUtil;
|
||||
import gov.nist.javax.sdp.TimeDescriptionImpl;
|
||||
import gov.nist.javax.sdp.fields.TimeField;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
@ -43,11 +45,12 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.sdp.*;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.*;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
@ -81,6 +84,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private SSRCFactory ssrcFactory;
|
||||
|
||||
@ -118,6 +124,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
@Autowired
|
||||
private RedisGbPlayMsgListener redisGbPlayMsgListener;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private SipSubscribe sipSubscribe;
|
||||
|
||||
@Autowired
|
||||
private SIPRequestHeaderProvider headerProvider;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@ -139,7 +153,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
String requesterId = SipUtils.getUserIdFromFromHeader(request);
|
||||
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
|
||||
if (requesterId == null || channelId == null) {
|
||||
logger.info("无法从FromHeader的Address中获取到平台id,返回400");
|
||||
logger.info("无法从请求中获取到平台id,返回400");
|
||||
// 参数不全, 发400,请求错误
|
||||
try {
|
||||
responseAck(request, Response.BAD_REQUEST);
|
||||
@ -149,6 +163,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("[INVITE] requesterId: {}, callId: {}, 来自:{}:{}",
|
||||
requesterId, callIdHeader.getCallId(), request.getRemoteAddress(), request.getRemotePort());
|
||||
|
||||
// 查询请求是否来自上级平台\设备
|
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
|
||||
@ -314,16 +330,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
if (channel != null) {
|
||||
device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
|
||||
if (device == null) {
|
||||
device = storager.queryDeviceInfoByPlatformIdAndChannelId(requesterId, channelId);
|
||||
if (device == null) {
|
||||
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channelId);
|
||||
try {
|
||||
responseAck(request, Response.SERVER_INTERNAL_ERROR);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] invite 未找到设备信息: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
logger.warn("点播平台{}的通道{}时未找到设备信息", requesterId, channel);
|
||||
try {
|
||||
responseAck(request, Response.SERVER_INTERNAL_ERROR);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] invite 未找到设备信息: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
mediaServerItem = playService.getNewMediaServerItem(device);
|
||||
if (mediaServerItem == null) {
|
||||
@ -343,6 +356,19 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
}else {
|
||||
ssrc = gb28181Sdp.getSsrc();
|
||||
}
|
||||
|
||||
// 限制同时只能存在一个回放流, 如果已有回放流就关闭
|
||||
if(!"Play".equalsIgnoreCase(sessionName)){
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, device.getDeviceId(), channelId);
|
||||
try {
|
||||
if(inviteInfo != null){
|
||||
logger.info("已存在回放流, 关闭已有回放流 {}", inviteInfo);
|
||||
inviteStreamService.removeInviteInfo(inviteInfo);
|
||||
cmder.streamByeCmd(device, inviteInfo.getChannelId(),
|
||||
inviteInfo.getStream(), null);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
String streamTypeStr = null;
|
||||
if (mediaTransmissionTCP) {
|
||||
if (tcpActive) {
|
||||
@ -354,7 +380,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
streamTypeStr = "UDP";
|
||||
}
|
||||
logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc);
|
||||
logger.info("device {}", JSONObject.toJSONString(device));
|
||||
SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
|
||||
device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
|
||||
|
||||
@ -400,7 +425,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
// 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口
|
||||
localPort = new Random().nextInt(65535) + 1;
|
||||
}
|
||||
content.append("m=video " + localPort + " RTP/AVP 96\r\n");
|
||||
if (sendRtpItem.isTcp()) {
|
||||
content.append("m=video " + localPort + " TCP/RTP/AVP 96\r\n");
|
||||
if (!sendRtpItem.isTcpActive()) {
|
||||
content.append("a=setup:active\r\n");
|
||||
} else {
|
||||
content.append("a=setup:passive\r\n");
|
||||
}
|
||||
}else {
|
||||
content.append("m=video " + localPort + " RTP/AVP 96\r\n");
|
||||
}
|
||||
content.append("a=sendonly\r\n");
|
||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||
content.append("y=" + sendRtpItem.getSsrc() + "\r\n");
|
||||
@ -408,19 +442,34 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
|
||||
|
||||
try {
|
||||
// 超时未收到Ack应该回复bye,当前等待时间为10秒
|
||||
dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
|
||||
logger.info("Ack 等待超时");
|
||||
mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
|
||||
// 回复bye
|
||||
try {
|
||||
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}, 60 * 1000);
|
||||
logger.info("content {}, platform {}", content, platform);
|
||||
responseSdpAck(request, content.toString(), platform);
|
||||
if(!"Download".equalsIgnoreCase(sessionName)){
|
||||
// 超时未收到Ack应该回复bye,当前等待时间为10秒
|
||||
dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
|
||||
logger.info("Ack 等待超时");
|
||||
mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
|
||||
// 回复bye
|
||||
try {
|
||||
cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}, 60 * 1000);
|
||||
|
||||
// sipSubscribe.addOkSubscribe("ACK_" + platform.getServerGBId()+"_"+callIdHeader.getCallId(), (eventResult) -> {
|
||||
// sipSubscribe.removeOkSubscribe("ACK_" + platform.getServerGBId()+"_"+callIdHeader.getCallId());
|
||||
//
|
||||
// SipSubscribe.Event okSubscribe = sipSubscribe.getOkSubscribe("ACK_DEVICE_" + channelId);
|
||||
// if(okSubscribe != null) {
|
||||
// okSubscribe.response(null);
|
||||
// //sipSubscribe.removeOkSubscribe("ACK_DEVICE_" + channelId);
|
||||
// }
|
||||
// // responseAck(streamInfo.getTransactionInfo())
|
||||
// });
|
||||
responseSdpAck(request, content.toString(), platform);
|
||||
}
|
||||
|
||||
// sipSubscribe.addOkSubscribe("ACK_" + channelId, (eventResult) -> {});
|
||||
|
||||
// tcp主动模式,回复sdp后开启监听
|
||||
if (sendRtpItem.isTcpActive()) {
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
@ -453,7 +502,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
}
|
||||
};
|
||||
ErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> {
|
||||
logger.info("errorEvent {} {} {}", statusCode, msg ,data);
|
||||
// 未知错误。直接转发设备点播的错误
|
||||
try {
|
||||
if (statusCode > 0) {
|
||||
@ -469,13 +517,59 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
|
||||
String startTimeStr = DateUtil.urlFormatter.format(start);
|
||||
String endTimeStr = DateUtil.urlFormatter.format(end);
|
||||
String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr;// + ssrc.substring(1);
|
||||
String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr;
|
||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
|
||||
if(ssrcInfo.getPort() <= 0){
|
||||
logger.warn("服务器端口资源不足");
|
||||
try {
|
||||
responseAck(request, Response.BUSY_HERE);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] invite 服务器端口资源不足: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
||||
// 写入redis, 超时时回复
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
|
||||
DateUtil.formatter.format(end),
|
||||
(String deviceCallId)->{
|
||||
// 忽略自动回复 ACK
|
||||
sipSubscribe.addOkSubscribe("ACK_IGNORE_" + deviceCallId, (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_IGNORE_" + deviceCallId);
|
||||
});
|
||||
|
||||
return null;
|
||||
},(SIPResponse response)->{
|
||||
|
||||
// 先订阅再发起
|
||||
// 订阅上级平台的 ACK 请求
|
||||
sipSubscribe.addOkSubscribe("ACK_" + callIdHeader.getCallId(), (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_" + callIdHeader.getCallId());
|
||||
try {
|
||||
String deviceContent = new String(response.getRawContent());
|
||||
Gb28181Sdp deviceGb28181Sdp = SipUtils.parseSDP(deviceContent);
|
||||
SessionDescription deviceSdp = deviceGb28181Sdp.getBaseSdb();
|
||||
SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(deviceSdp.getOrigin().getUsername(), response.getRemoteAddress().getHostAddress() + ":" + response.getRemotePort());
|
||||
|
||||
logger.info("收到上级 callId => {} 的 ACK 请求, 向 下级 {} 转发 ACK", callIdHeader.getCallId(), deviceSdp.getOrigin().getUsername());
|
||||
// 收到上级的 ACK 后, 向设备转发 ACK 并开启 ZLM RTP 收流 + RTP 转发
|
||||
Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
|
||||
sipSender.transmitRequest(response.getLocalAddress().getHostAddress(), reqAck);
|
||||
} catch (ParseException | SdpParseException | InvalidArgumentException | SipException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// 向上级平台回复 INVITE OK
|
||||
responseSdpAck(request, new String(request.getRawContent()), platform);
|
||||
} catch (SipException | InvalidArgumentException |
|
||||
ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
(code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()){
|
||||
hookEvent.run(code, msg, data);
|
||||
@ -487,13 +581,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
errorEvent.run(code, msg, data);
|
||||
}
|
||||
});
|
||||
}else if ("Download".equalsIgnoreCase(sessionName)) {
|
||||
} else if ("Download".equalsIgnoreCase(sessionName)) {
|
||||
// 获取指定的下载速度
|
||||
Vector sdpMediaDescriptions = sdp.getMediaDescriptions(true);
|
||||
MediaDescription mediaDescription = null;
|
||||
String downloadSpeed = "1";
|
||||
if (sdpMediaDescriptions.size() > 0) {
|
||||
mediaDescription = (MediaDescription)sdpMediaDescriptions.get(0);
|
||||
mediaDescription = (MediaDescription) sdpMediaDescriptions.get(0);
|
||||
}
|
||||
if (mediaDescription != null) {
|
||||
downloadSpeed = mediaDescription.getAttribute("downloadspeed");
|
||||
@ -502,37 +596,112 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD);
|
||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
|
||||
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
||||
sendRtpItem.setLocalPort(0);
|
||||
// 写入redis, 超时时回复
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
|
||||
playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
|
||||
DateUtil.formatter.format(end), NumberUtils.createDouble(downloadSpeed).intValue(),
|
||||
DateUtil.formatter.format(end), NumberUtils.createDouble(downloadSpeed).intValue(),(String deviceCallId)->{
|
||||
// 忽略自动回复 ACK
|
||||
sipSubscribe.addOkSubscribe("ACK_IGNORE_" + deviceCallId, (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_IGNORE_" + deviceCallId);
|
||||
});
|
||||
|
||||
return null;
|
||||
},(SIPResponse response)->{
|
||||
|
||||
// 先订阅再发起
|
||||
// 订阅上级平台的 ACK 请求
|
||||
sipSubscribe.addOkSubscribe("ACK_" + callIdHeader.getCallId(), (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_" + callIdHeader.getCallId());
|
||||
try {
|
||||
String deviceContent = new String(response.getRawContent());
|
||||
Gb28181Sdp deviceGb28181Sdp = SipUtils.parseSDP(deviceContent);
|
||||
SessionDescription deviceSdp = deviceGb28181Sdp.getBaseSdb();
|
||||
SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(deviceSdp.getOrigin().getUsername(), response.getRemoteAddress().getHostAddress() + ":" + response.getRemotePort());
|
||||
|
||||
logger.info("收到上级 callId => {} 的 ACK 请求, 向 下级 {} 转发 ACK", callIdHeader.getCallId(), deviceSdp.getOrigin().getUsername());
|
||||
// 收到上级的 ACK 后, 向设备转发 ACK 并开启 ZLM RTP 收流 + RTP 转发
|
||||
Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
|
||||
sipSender.transmitRequest(response.getLocalAddress().getHostAddress(), reqAck);
|
||||
} catch (ParseException | SdpParseException | InvalidArgumentException | SipException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// 向上级平台回复 INVITE OK
|
||||
responseSdpAck(request, new String(request.getRawContent()), platform);
|
||||
} catch (SipException | InvalidArgumentException |
|
||||
ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
(code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()){
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
hookEvent.run(code, msg, data);
|
||||
}else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){
|
||||
} else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) {
|
||||
logger.info("[录像下载]超时, 用户:{}, 通道:{}", username, channelId);
|
||||
redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
|
||||
errorEvent.run(code, msg, data);
|
||||
}else {
|
||||
} else {
|
||||
errorEvent.run(code, msg, data);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
|
||||
SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()){
|
||||
hookEvent.run(code, msg, data);
|
||||
}else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){
|
||||
logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId);
|
||||
redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
|
||||
errorEvent.run(code, msg, data);
|
||||
}else {
|
||||
errorEvent.run(code, msg, data);
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
sendRtpItem.setPlayType(InviteStreamType.PLAY);
|
||||
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
||||
sendRtpItem.setStreamId(streamId);
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, (String deviceCallId) -> {
|
||||
// 忽略自动回复 ACK
|
||||
sipSubscribe.addOkSubscribe("ACK_IGNORE_" + deviceCallId, (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_IGNORE_" + deviceCallId);
|
||||
});
|
||||
|
||||
return null;
|
||||
}, (SIPResponse response) -> {
|
||||
|
||||
// 先订阅再发起
|
||||
// 订阅上级平台的 ACK 请求
|
||||
sipSubscribe.addOkSubscribe("ACK_" + callIdHeader.getCallId(), (eventResult) -> {
|
||||
sipSubscribe.removeOkSubscribe("ACK_" + callIdHeader.getCallId());
|
||||
try {
|
||||
String deviceContent = new String(response.getRawContent());
|
||||
Gb28181Sdp deviceGb28181Sdp = SipUtils.parseSDP(deviceContent);
|
||||
SessionDescription deviceSdp = deviceGb28181Sdp.getBaseSdb();
|
||||
SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(deviceSdp.getOrigin().getUsername(), response.getRemoteAddress().getHostAddress() + ":" + response.getRemotePort());
|
||||
|
||||
logger.info("收到上级 callId => {} 的 ACK 请求, 向 下级 {} 转发 ACK", callIdHeader.getCallId(), deviceSdp.getOrigin().getUsername());
|
||||
// 收到上级的 ACK 后, 向设备转发 ACK 并开启 ZLM RTP 收流 + RTP 转发
|
||||
Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
|
||||
sipSender.transmitRequest(response.getLocalAddress().getHostAddress(), reqAck);
|
||||
} catch (ParseException | SdpParseException | InvalidArgumentException |
|
||||
SipException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// 向上级平台回复 INVITE OK
|
||||
responseSdpAck(request, new String(request.getRawContent()), platform);
|
||||
} catch (SipException | InvalidArgumentException |
|
||||
ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
}, ((code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
hookEvent.run(code, msg, data);
|
||||
} else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) {
|
||||
logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId);
|
||||
redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
|
||||
errorEvent.run(code, msg, data);
|
||||
} else {
|
||||
errorEvent.run(code, msg, data);
|
||||
}
|
||||
}));
|
||||
sendRtpItem.setSsrc(ssrcInfo.getSsrc());
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
|
||||
@ -714,9 +883,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
zlmHttpHookSubscribe.removeSubscribe(hookSubscribe);
|
||||
dynamicTask.stop(callIdHeader.getCallId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if ("push".equals(gbStream.getStreamType())) {
|
||||
if (!platform.isStartOfflinePush()) {
|
||||
// 平台设置中关闭了拉起离线的推流则直接回复
|
||||
@ -739,13 +905,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
|
||||
logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
|
||||
try {
|
||||
redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
|
||||
mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
|
||||
responseAck(request, Response.REQUEST_TIMEOUT); // 超时
|
||||
} catch (SipException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
} catch (InvalidArgumentException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
} catch (ParseException e) {
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
}
|
||||
}, userSetting.getPlatformPlayTimeout());
|
||||
@ -756,6 +919,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
// 添加在本机上线的通知
|
||||
mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
|
||||
dynamicTask.stop(callIdHeader.getCallId());
|
||||
redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
|
||||
if (serverId.equals(userSetting.getServerId())) {
|
||||
SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
|
||||
app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
|
||||
@ -820,7 +984,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
// 发送redis消息
|
||||
redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(),
|
||||
streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId,
|
||||
channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> {
|
||||
channelId, mediaTransmissionTCP, platform.isRtcp(),platform.getName(), responseSendItemMsg -> {
|
||||
SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem();
|
||||
if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
|
||||
logger.warn("服务器端口资源不足");
|
||||
|
53
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
Normal file → Executable file
53
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
Normal file → Executable file
@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.slf4j.Logger;
|
||||
@ -185,6 +186,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
// 判断此通道是否存在
|
||||
DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId());
|
||||
if (deviceChannel != null) {
|
||||
logger.info("[增加通道] 已存在,不发送通知只更新,设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
|
||||
channel.setId(deviceChannel.getId());
|
||||
updateChannelMap.put(channel.getChannelId(), channel);
|
||||
if (updateChannelMap.keySet().size() > 300) {
|
||||
@ -222,6 +224,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId());
|
||||
if (deviceChannelForUpdate != null) {
|
||||
channel.setId(deviceChannelForUpdate.getId());
|
||||
channel.setUpdateTime(DateUtil.getNow());
|
||||
updateChannelMap.put(channel.getChannelId(), channel);
|
||||
if (updateChannelMap.keySet().size() > 300) {
|
||||
executeSaveForUpdate();
|
||||
@ -244,11 +247,11 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
// 转发变化信息
|
||||
eventPublisher.catalogEventPublish(null, channel, event);
|
||||
|
||||
if (updateChannelMap.keySet().size() > 0
|
||||
|| addChannelMap.keySet().size() > 0
|
||||
|| updateChannelOnlineList.size() > 0
|
||||
|| updateChannelOfflineList.size() > 0
|
||||
|| deleteChannelList.size() > 0) {
|
||||
if (!updateChannelMap.keySet().isEmpty()
|
||||
|| !addChannelMap.keySet().isEmpty()
|
||||
|| !updateChannelOnlineList.isEmpty()
|
||||
|| !updateChannelOfflineList.isEmpty()
|
||||
|| !deleteChannelList.isEmpty()) {
|
||||
|
||||
if (!dynamicTask.contains(talkKey)) {
|
||||
dynamicTask.startDelay(talkKey, this::executeSave, 1000);
|
||||
@ -262,16 +265,36 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSave(){
|
||||
executeSaveForAdd();
|
||||
executeSaveForUpdate();
|
||||
executeSaveForDelete();
|
||||
executeSaveForOnline();
|
||||
executeSaveForOffline();
|
||||
try {
|
||||
executeSaveForAdd();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的增加通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForUpdate();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的更新通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForDelete();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的删除通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForOnline();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的通道上线] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForOffline();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的通道离线] 异常: ", e );
|
||||
}
|
||||
dynamicTask.stop(talkKey);
|
||||
}
|
||||
|
||||
private void executeSaveForUpdate(){
|
||||
if (updateChannelMap.values().size() > 0) {
|
||||
if (!updateChannelMap.values().isEmpty()) {
|
||||
ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values());
|
||||
updateChannelMap.clear();
|
||||
deviceChannelService.batchUpdateChannel(deviceChannels);
|
||||
@ -280,7 +303,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSaveForAdd(){
|
||||
if (addChannelMap.values().size() > 0) {
|
||||
if (!addChannelMap.values().isEmpty()) {
|
||||
ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values());
|
||||
addChannelMap.clear();
|
||||
deviceChannelService.batchAddChannel(deviceChannels);
|
||||
@ -288,21 +311,21 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSaveForDelete(){
|
||||
if (deleteChannelList.size() > 0) {
|
||||
if (!deleteChannelList.isEmpty()) {
|
||||
deviceChannelService.deleteChannels(deleteChannelList);
|
||||
deleteChannelList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSaveForOnline(){
|
||||
if (updateChannelOnlineList.size() > 0) {
|
||||
if (!updateChannelOnlineList.isEmpty()) {
|
||||
deviceChannelService.channelsOnline(updateChannelOnlineList);
|
||||
updateChannelOnlineList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSaveForOffline(){
|
||||
if (updateChannelOfflineList.size() > 0) {
|
||||
if (!updateChannelOfflineList.isEmpty()) {
|
||||
deviceChannelService.channelsOffline(updateChannelOfflineList);
|
||||
updateChannelOfflineList.clear();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user