mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-24 20:28:59 +08:00
Compare commits
1682 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da2e33a040 | ||
|
|
f2d260bfa4 | ||
|
|
783c7244f9 | ||
|
|
c9287e0e63 | ||
|
|
69b84d115c | ||
|
|
1745b898b1 | ||
|
|
5ba4c85249 | ||
|
|
03c87bb46d | ||
|
|
dff5a76e9e | ||
|
|
50386f4ca4 | ||
|
|
de6ba2ec80 | ||
|
|
ce126015d9 | ||
|
|
f2337c3d43 | ||
|
|
41b59d322a | ||
|
|
dfea7c111e | ||
|
|
3d5d672297 | ||
|
|
e4dcc6f342 | ||
|
|
9847249611 | ||
|
|
19742a54ec | ||
|
|
5af9ae7a80 | ||
|
|
78962a4a75 | ||
|
|
9a35d826aa | ||
|
|
c9cdc89d35 | ||
|
|
33b75703ba | ||
|
|
ca55aa3a24 | ||
|
|
95307c3902 | ||
|
|
89c8eae7e2 | ||
|
|
91614772dc | ||
|
|
cd497ab4dc | ||
|
|
f81895905e | ||
|
|
d82fafaa7a | ||
|
|
0ea01acc46 | ||
|
|
df55792a68 | ||
|
|
6a19c45269 | ||
|
|
23ee345441 | ||
|
|
0e8ff253f3 | ||
|
|
89bddb0bc4 | ||
|
|
77bbca9bb3 | ||
|
|
1acd4d8d58 | ||
|
|
4db72a712d | ||
|
|
da2b7ba08e | ||
|
|
f8b49411bf | ||
|
|
a04b0d99b0 | ||
|
|
9e9735f617 | ||
|
|
f906b36f01 | ||
|
|
a9d1f4f854 | ||
|
|
d017ae905f | ||
|
|
bede280507 | ||
|
|
ea130047bc | ||
|
|
d77d8de63e | ||
|
|
f5413d9202 | ||
|
|
559fc8f216 | ||
|
|
34b2df911d | ||
|
|
3d5a8a8cbd | ||
|
|
2b07097e14 | ||
|
|
372e943d8b | ||
|
|
95afcedc4f | ||
|
|
c1dc8f017c | ||
|
|
dbeddca263 | ||
|
|
e65d133dec | ||
|
|
b5e1dea1c2 | ||
|
|
3f19469939 | ||
|
|
87874b037a | ||
|
|
adda6841d1 | ||
|
|
a8092b921b | ||
|
|
930e4d69d1 | ||
|
|
d9219df45b | ||
|
|
a6d4ec28db | ||
|
|
b29e13f777 | ||
|
|
9363b78ff6 | ||
|
|
eba411fec7 | ||
|
|
9afe99e134 | ||
|
|
6678856178 | ||
|
|
a1fea38c2c | ||
|
|
2d3265e66d | ||
|
|
f6d4400db9 | ||
|
|
6d892a9266 | ||
|
|
356fa08da5 | ||
|
|
2225f8c890 | ||
|
|
d1a89739f9 | ||
|
|
6ec6896763 | ||
|
|
9fb718d610 | ||
|
|
c913b89a47 | ||
|
|
58b45693b7 | ||
|
|
29d3ece9b1 | ||
|
|
7e5db75230 | ||
|
|
283c0b9845 | ||
|
|
071a0f1651 | ||
|
|
1a116557a4 | ||
|
|
1468297626 | ||
|
|
87e94fdf52 | ||
|
|
64e15c33c8 | ||
|
|
7170f435d1 | ||
|
|
9942be0493 | ||
|
|
eaad36277f | ||
|
|
37cc498568 | ||
|
|
8a3191340a | ||
|
|
0f4e998f0a | ||
|
|
0c93b649ba | ||
|
|
947d269877 | ||
|
|
b4b9453948 | ||
|
|
b99a4cd095 | ||
|
|
a363d5aa46 | ||
|
|
ae442dabb4 | ||
|
|
1477c88397 | ||
|
|
4172462938 | ||
|
|
27341ba4f8 | ||
|
|
7443076094 | ||
|
|
a764bb4b1d | ||
|
|
57130e1af7 | ||
|
|
3f8a354c99 | ||
|
|
0b10d92929 | ||
|
|
1a1c55e661 | ||
|
|
87768f9e8b | ||
|
|
d079f50364 | ||
|
|
72a89835c5 | ||
|
|
39d686810b | ||
|
|
d936626001 | ||
|
|
cdce1c5ea6 | ||
|
|
d59530a54f | ||
|
|
fe480811fb | ||
|
|
2e3e0d34c3 | ||
|
|
1e2984d0d9 | ||
|
|
3e9fe693c7 | ||
|
|
63161838d8 | ||
|
|
7c92951ae9 | ||
|
|
59a25854ef | ||
|
|
3ca5768974 | ||
|
|
9a2dce43dd | ||
|
|
b7fce4317b | ||
|
|
97d9514b00 | ||
|
|
58f88708fa | ||
|
|
d79c874aa5 | ||
|
|
58917c1ff8 | ||
|
|
13b171a62d | ||
|
|
f0a601922a | ||
|
|
d90090b35e | ||
|
|
094d1142e7 | ||
|
|
eb09d1c925 | ||
|
|
bd5d75361e | ||
|
|
5d7c0c635b | ||
|
|
606f538bf3 | ||
|
|
574c0eea27 | ||
|
|
4730cbc543 | ||
|
|
5c63359550 | ||
|
|
ec3607f779 | ||
|
|
7efd0f8098 | ||
|
|
2a7c30a21a | ||
|
|
2639c3ee3f | ||
|
|
547e0153cb | ||
|
|
423664fcfa | ||
|
|
c986c230ef | ||
|
|
7c6001f76e | ||
|
|
d3620946ac | ||
|
|
479643221c | ||
|
|
c9ef8bcf6a | ||
|
|
d655a7c2f6 | ||
|
|
306861d3b4 | ||
|
|
7abab41eed | ||
|
|
acc2691e33 | ||
|
|
21a65956b0 | ||
|
|
9738275ad1 | ||
|
|
7265034703 | ||
|
|
9bcc45591d | ||
|
|
38d657ba0e | ||
|
|
6a0d16c5bb | ||
|
|
490d4abb56 | ||
|
|
a7d0f7fc99 | ||
|
|
0d2d3ff528 | ||
|
|
526169f0aa | ||
|
|
42940ff0e3 | ||
|
|
e9b943363d | ||
|
|
01e98ff10c | ||
|
|
d38981a17d | ||
|
|
7612e91691 | ||
|
|
76b0f20033 | ||
|
|
b78c0f8a29 | ||
|
|
ea93c7c8fc | ||
|
|
8ac1952974 | ||
|
|
b4514a5bbf | ||
|
|
568053b06d | ||
|
|
bb180bfc39 | ||
|
|
5ee635caed | ||
|
|
5dfd7c8597 | ||
|
|
fe61b75d7e | ||
|
|
e7bf565418 | ||
|
|
12071f6251 | ||
|
|
72ed2e3ed0 | ||
|
|
d7c1f134fe | ||
|
|
5072d9f7ad | ||
|
|
5d42a1247a | ||
|
|
ce64be22bd | ||
|
|
36f9386e8d | ||
|
|
e9dc963805 | ||
|
|
8854322997 | ||
|
|
6018f1e8ca | ||
|
|
68f8ebb543 | ||
|
|
301f0218fd | ||
|
|
a9c4a56893 | ||
|
|
3ea3d72f11 | ||
|
|
33da5bf4a7 | ||
|
|
e3de01948a | ||
|
|
3cd92aaf54 | ||
|
|
ab4e1996dd | ||
|
|
b9ef082abf | ||
|
|
dac7186da3 | ||
|
|
1fd6cc2b5e | ||
|
|
0b7da9790a | ||
|
|
a9e0e0ead6 | ||
|
|
079754f1a9 | ||
|
|
c45b5b1e86 | ||
|
|
2115cc685c | ||
|
|
b99e56fc19 | ||
|
|
74c057eb84 | ||
|
|
e8ececc0dc | ||
|
|
ad120b7736 | ||
|
|
61c0711e79 | ||
|
|
81c3f6fce0 | ||
|
|
0a4416e633 | ||
|
|
6bb712854d | ||
|
|
46959e2407 | ||
|
|
debbb049b0 | ||
|
|
375377fef9 | ||
|
|
d5758dd6a3 | ||
|
|
d5deffea58 | ||
|
|
fadb43d9a1 | ||
|
|
044b641df0 | ||
|
|
fbbacdb2ff | ||
|
|
4bfd7acd96 | ||
|
|
ff03225cf4 | ||
|
|
8e820c0e47 | ||
|
|
d718314324 | ||
|
|
1c653ec1b1 | ||
|
|
fe16ddadce | ||
|
|
7a978054cc | ||
|
|
8ed3b5a747 | ||
|
|
6885150800 | ||
|
|
35d33a1c7d | ||
|
|
93a16bbd3c | ||
|
|
d3cf6a4985 | ||
|
|
8ef7200c32 | ||
|
|
e43da5ba86 | ||
|
|
10428b4340 | ||
|
|
43b7c05cd7 | ||
|
|
057f64b04c | ||
|
|
0971d783f3 | ||
|
|
54aabad3e8 | ||
|
|
606fbb5fec | ||
|
|
5093c27ba5 | ||
|
|
1d3661c946 | ||
|
|
304f7a068d | ||
|
|
7ea91be3fc | ||
|
|
d15464b1ae | ||
|
|
150435f24e | ||
|
|
e49507cd14 | ||
|
|
ad3cc3ebb6 | ||
|
|
ecaf53836d | ||
|
|
8fc36e7b24 | ||
|
|
1dbbac2aa3 | ||
|
|
4e5775fde4 | ||
|
|
9d81c7c366 | ||
|
|
2df0441f0f | ||
|
|
4216002ce5 | ||
|
|
1af6f4e151 | ||
|
|
05f284bc11 | ||
|
|
40c19b3ad4 | ||
|
|
d1d972cca0 | ||
|
|
2a969921d6 | ||
|
|
4b3e1f5187 | ||
|
|
561963aa26 | ||
|
|
6c2c192836 | ||
|
|
f0730f2295 | ||
|
|
9df91d2b63 | ||
|
|
09da1941fd | ||
|
|
613c8e4c28 | ||
|
|
7b407fd34d | ||
|
|
fb7ff7a803 | ||
|
|
0c1f0e0522 | ||
|
|
b5d771e9aa | ||
|
|
2f64255895 | ||
|
|
5b629a5c40 | ||
|
|
b749cf52c3 | ||
|
|
b9a36a9223 | ||
|
|
32debf6e6b | ||
|
|
06f6ae01c9 | ||
|
|
db4d8ad802 | ||
|
|
9c82de9c9e | ||
|
|
8329835528 | ||
|
|
8e624aa31b | ||
|
|
a2e8741517 | ||
|
|
3b7c107e8f | ||
|
|
558bc3f971 | ||
|
|
90a326f380 | ||
|
|
867dc1ae35 | ||
|
|
3f555464f7 | ||
|
|
c0c0782258 | ||
|
|
377f57bcb6 | ||
|
|
a51253f1e5 | ||
|
|
e674e94da6 | ||
|
|
93a415f6d3 | ||
|
|
9364b97692 | ||
|
|
030915c9ea | ||
|
|
10882c309a | ||
|
|
8232fde160 | ||
|
|
45c3474d4d | ||
|
|
c5a9e85343 | ||
|
|
8c7ef59583 | ||
|
|
36404b5c92 | ||
|
|
9949a117be | ||
|
|
a3896db4f5 | ||
|
|
f668062cab | ||
|
|
bac0721078 | ||
|
|
e29d7244d8 | ||
|
|
5a34b91a7a | ||
|
|
eaac8b1428 | ||
|
|
6c6275dc88 | ||
|
|
bd350ae679 | ||
|
|
cadee28c68 | ||
|
|
3534828a99 | ||
|
|
e1c5777e25 | ||
|
|
63553d4dd3 | ||
|
|
6033d779fc | ||
|
|
97db27e61f | ||
|
|
8ed861c05f | ||
|
|
4d416657bf | ||
|
|
ede0399275 | ||
|
|
1a28ada04c | ||
|
|
8ac771cde4 | ||
|
|
c6afbbfc73 | ||
|
|
5ba71e8109 | ||
|
|
a0d2922aca | ||
|
|
446610b9df | ||
|
|
4905eea503 | ||
|
|
519fc128f6 | ||
|
|
cc10955483 | ||
|
|
e0bd47bb87 | ||
|
|
fb0c3c4a06 | ||
|
|
ceef1fdaf2 | ||
|
|
e1ac287ed1 | ||
|
|
29cd3a5945 | ||
|
|
cab082166b | ||
|
|
711dfd4da9 | ||
|
|
643948331d | ||
|
|
119030f1a5 | ||
|
|
3efee3dc52 | ||
|
|
70716d5121 | ||
|
|
a7d11ead62 | ||
|
|
017830e433 | ||
|
|
bceb175c75 | ||
|
|
98277c6b71 | ||
|
|
b227fbe523 | ||
|
|
ac6659a293 | ||
|
|
30a24ced1d | ||
|
|
3d1f4ae2ed | ||
|
|
e86aff049c | ||
|
|
8ec0ba7c9e | ||
|
|
c2898f0b2e | ||
|
|
0747374378 | ||
|
|
a0c2fea833 | ||
|
|
811c1a445f | ||
|
|
72d3041e7e | ||
|
|
503180e7ec | ||
|
|
8ad548cad7 | ||
|
|
85d9acf605 | ||
|
|
fc93c5ffcb | ||
|
|
d6b0a9314c | ||
|
|
83bc07c3ff | ||
|
|
6ca680cd41 | ||
|
|
2b533dcb2b | ||
|
|
13a5a09f98 | ||
|
|
75ff7ebdbe | ||
|
|
6d8f3a1fc8 | ||
|
|
a11b411912 | ||
|
|
2dba817c69 | ||
|
|
d4df9a545f | ||
|
|
cae21391e5 | ||
|
|
573b22d2c2 | ||
|
|
14d4112a9d | ||
|
|
28aa9db9c5 | ||
|
|
d50c349e00 | ||
|
|
905362c59c | ||
|
|
97e7d44310 | ||
|
|
bb71a1ef23 | ||
|
|
de2771d008 | ||
|
|
02de34b65a | ||
|
|
c6e14889f2 | ||
|
|
f843732790 | ||
|
|
80e7ff0fc1 | ||
|
|
2964db6bdd | ||
|
|
5fbd94ec74 | ||
|
|
1d8d31d4f0 | ||
|
|
707c3eed99 | ||
|
|
e33a81ad36 | ||
|
|
0f7d216379 | ||
|
|
f0052e97a6 | ||
|
|
5c6076d48d | ||
|
|
883bd31249 | ||
|
|
d7b5fde3c7 | ||
|
|
f4273efef0 | ||
|
|
471dc966d9 | ||
|
|
50368654a4 | ||
|
|
b1e1cc04ce | ||
|
|
554f67e295 | ||
|
|
278bd09a6c | ||
|
|
300d083038 | ||
|
|
34664f0025 | ||
|
|
7aaa803813 | ||
|
|
b075b3ec1c | ||
|
|
0f3f4b0f5b | ||
|
|
fd5ed78442 | ||
|
|
d516e7dcb4 | ||
|
|
6a1f1ebf9d | ||
|
|
6ba5c02dd6 | ||
|
|
c9b8f90859 | ||
|
|
70a0bf6d5c | ||
|
|
4caf8d6fab | ||
|
|
aa90593158 | ||
|
|
9da5531483 | ||
|
|
9483459ba7 | ||
|
|
ae57883770 | ||
|
|
8cb5a89d10 | ||
|
|
1a35fb0d4d | ||
|
|
1a2483c68c | ||
|
|
6c806238b2 | ||
|
|
ea6e07a38b | ||
|
|
ec6b07b275 | ||
|
|
e85a03a1ca | ||
|
|
5d66b7677f | ||
|
|
3932834172 | ||
|
|
d2e8294a1a | ||
|
|
b06aa66ad8 | ||
|
|
c45b48d949 | ||
|
|
f779af1f65 | ||
|
|
78d039cd5f | ||
|
|
fdbd5418c7 | ||
|
|
5df42466fd | ||
|
|
ff2bed87f2 | ||
|
|
765e7d0b1e | ||
|
|
71ab6d42c8 | ||
|
|
2ea2a662ef | ||
|
|
c2d45349a4 | ||
|
|
1b5cf410b7 | ||
|
|
3e79e2bed0 | ||
|
|
2a1f933702 | ||
|
|
251d3b487f | ||
|
|
e55ec48c7d | ||
|
|
7ce2195adb | ||
|
|
537b79f1c2 | ||
|
|
e4c4d22f56 | ||
|
|
c4d244398c | ||
|
|
47260cdaf0 | ||
|
|
7ef13058c7 | ||
|
|
8066cb1804 | ||
|
|
c5af6062fa | ||
|
|
908a2eba20 | ||
|
|
6f43957703 | ||
|
|
897ea28cf4 | ||
|
|
d056ddbff1 | ||
|
|
f157350059 | ||
|
|
7e3d99bda3 | ||
|
|
c7c53e1d94 | ||
|
|
b912ee3f6f | ||
|
|
06c05ad8e5 | ||
|
|
7f411400d5 | ||
|
|
f24f234869 | ||
|
|
4e384e7811 | ||
|
|
5143448163 | ||
|
|
8e5e9f7cbc | ||
|
|
5ea7fd01bf | ||
|
|
8f3f6bc774 | ||
|
|
7f1524b42f | ||
|
|
4b7db4689d | ||
|
|
92831ecb43 | ||
|
|
d486f3f306 | ||
|
|
bfb7468f62 | ||
|
|
2e417d41db | ||
|
|
b17f68cbfb | ||
|
|
8a22a523d6 | ||
|
|
97fe752a4e | ||
|
|
cc4ea122a2 | ||
|
|
db995d29e5 | ||
|
|
c22dde8008 | ||
|
|
462d888894 | ||
|
|
9311b914ad | ||
|
|
c5e0488210 | ||
|
|
f548c27179 | ||
|
|
1f5f405b52 | ||
|
|
cd923ab838 | ||
|
|
aacdff92d2 | ||
|
|
32160d388a | ||
|
|
72e31929eb | ||
|
|
29014bb40e | ||
|
|
e9d0a65536 | ||
|
|
f7a3b68834 | ||
|
|
dcc9d3b588 | ||
|
|
b8f6f65943 | ||
|
|
3dacdda21a | ||
|
|
49b766120f | ||
|
|
2d7e1553f8 | ||
|
|
d5d41213b0 | ||
|
|
328df00d2e | ||
|
|
e4a5bf8234 | ||
|
|
d6ee0f216c | ||
|
|
0246ef6b6a | ||
|
|
7fd40518fd | ||
|
|
95eb53edf6 | ||
|
|
4cdf2962cd | ||
|
|
5bf8ccd1fd | ||
|
|
dd9fbbcfa7 | ||
|
|
72d8fd5be0 | ||
|
|
b577229ed3 | ||
|
|
4ae870b799 | ||
|
|
0590e74b30 | ||
|
|
b9956ba800 | ||
|
|
fef6259d09 | ||
|
|
e24f19e88b | ||
|
|
cc6de1e71c | ||
|
|
b0240a1c95 | ||
|
|
8acdec333b | ||
|
|
eafcbb81f9 | ||
|
|
4b083463c8 | ||
|
|
78e834e04f | ||
|
|
2ed1893620 | ||
|
|
35f188a7dd | ||
|
|
07f577a9dd | ||
|
|
25c72b50c0 | ||
|
|
e07346ebea | ||
|
|
699b466291 | ||
|
|
f0f24ff96f | ||
|
|
1113997c71 | ||
|
|
487fb6e5c9 | ||
|
|
62908a323c | ||
|
|
021131271a | ||
|
|
c20fa4dbd2 | ||
|
|
b1826678da | ||
|
|
1630338f4e | ||
|
|
78af3d979c | ||
|
|
8346dfb1f5 | ||
|
|
5ecb4e4fe4 | ||
|
|
ec9ff23b23 | ||
|
|
149e9931e7 | ||
|
|
58b62094bd | ||
|
|
d357074ad4 | ||
|
|
d9bacc129b | ||
|
|
28d869b099 | ||
|
|
d04e87718a | ||
|
|
8d81bf60c9 | ||
|
|
4fe9094ff7 | ||
|
|
4cfde45755 | ||
|
|
c28844dbeb | ||
|
|
837ea7c8d6 | ||
|
|
6c85ac8827 | ||
|
|
c8eb8bf35d | ||
|
|
0f6cbddd57 | ||
|
|
530b4755bf | ||
|
|
679395b3fe | ||
|
|
9293442836 | ||
|
|
4841b412f3 | ||
|
|
f03575ad89 | ||
|
|
e0e5428ebd | ||
|
|
015f7edae2 | ||
|
|
d5414f5d91 | ||
|
|
4bc3512d42 | ||
|
|
4c305994ca | ||
|
|
788e2cba04 | ||
|
|
b79b79970e | ||
|
|
8b0f4de516 | ||
|
|
a17000ad6d | ||
|
|
c9f63c58df | ||
|
|
c311b1c706 | ||
|
|
072451afae | ||
|
|
7349793463 | ||
|
|
c0144eab86 | ||
|
|
ba79b25944 | ||
|
|
3fb34b12a0 | ||
|
|
b6c17e76c2 | ||
|
|
1201f20d79 | ||
|
|
98ae8e692e | ||
|
|
8342dbff4e | ||
|
|
a22aa0f9a7 | ||
|
|
b49d221ec1 | ||
|
|
f1be315147 | ||
|
|
8aaac2a3d4 | ||
|
|
bd07d30e47 | ||
|
|
54e103f00f | ||
|
|
5404d8f7ab | ||
|
|
1364e02c67 | ||
|
|
b4818e2f9a | ||
|
|
734cf57d4a | ||
|
|
9236610ec1 | ||
|
|
c33828a5d9 | ||
|
|
faadb03e46 | ||
|
|
3a0c4c51d2 | ||
|
|
6c28c2b91e | ||
|
|
5226df6194 | ||
|
|
1ad23a3cbb | ||
|
|
c4149ca304 | ||
|
|
68b02fe950 | ||
|
|
d9408523a5 | ||
|
|
40ad0f063a | ||
|
|
40d85e8926 | ||
|
|
e655f719e6 | ||
|
|
ede0ea02c5 | ||
|
|
e579575b21 | ||
|
|
06ffcc9fdf | ||
|
|
774d03e510 | ||
|
|
adcac9dfe6 | ||
|
|
399e14c70c | ||
|
|
ec8b51033b | ||
|
|
ca5d167b6a | ||
|
|
fcd1b001d1 | ||
|
|
1cabbefe04 | ||
|
|
ecefe22c95 | ||
|
|
64db77b9a2 | ||
|
|
19d7360ad5 | ||
|
|
2f014cd827 | ||
|
|
7fb84205d9 | ||
|
|
47e1127c5f | ||
|
|
e036b59306 | ||
|
|
f4904c3b53 | ||
|
|
3002a63ba5 | ||
|
|
b69717e6c3 | ||
|
|
d07962953f | ||
|
|
857cf0d21e | ||
|
|
5f08c2615d | ||
|
|
e87428ef33 | ||
|
|
03fd54fe70 | ||
|
|
086c2c8253 | ||
|
|
05c19a32ea | ||
|
|
99d174906a | ||
|
|
82e30a326a | ||
|
|
2963a9cdca | ||
|
|
288da75b2b | ||
|
|
0943a496dd | ||
|
|
e5dd7cc2fa | ||
|
|
358836ef9f | ||
|
|
aab4fac6c5 | ||
|
|
525540b603 | ||
|
|
b30eeb4694 | ||
|
|
3faf0aa2fc | ||
|
|
fd728dec5d | ||
|
|
08b14b72d4 | ||
|
|
de2e005abf | ||
|
|
0fc75239a6 | ||
|
|
390fe30a0d | ||
|
|
633f49fcd2 | ||
|
|
30c0ba93b9 | ||
|
|
e935fb9621 | ||
|
|
5ce8bb1d08 | ||
|
|
1acd12980a | ||
|
|
683235dd8a | ||
|
|
65fe183ad4 | ||
|
|
f39d5d355c | ||
|
|
eccc8e0ff0 | ||
|
|
dd4d8e775c | ||
|
|
7a7f857b2f | ||
|
|
10882b7d93 | ||
|
|
e669b81005 | ||
|
|
28a81d9539 | ||
|
|
6bf5e4a6b8 | ||
|
|
a51eee93f4 | ||
|
|
bece2555c2 | ||
|
|
d98d405009 | ||
|
|
8d0881632c | ||
|
|
e8b81da897 | ||
|
|
acf4fbf750 | ||
|
|
b4f1921d33 | ||
|
|
94b4816f53 | ||
|
|
b6ddafde3e | ||
|
|
b01036818f | ||
|
|
ad7da1a0c3 | ||
|
|
1e0818d9d9 | ||
|
|
a4686f01c3 | ||
|
|
84d76f9aab | ||
|
|
b90bf5eb86 | ||
|
|
fe258f3fe5 | ||
|
|
d339494594 | ||
|
|
adfaf13055 | ||
|
|
8abfeb5923 | ||
|
|
c1a027a771 | ||
|
|
5f3094d79b | ||
|
|
925b81aca8 | ||
|
|
c0c8437966 | ||
|
|
1d27b2fc4a | ||
|
|
5da43e7808 | ||
|
|
5edbb558ae | ||
|
|
7347cc1df2 | ||
|
|
20cac11b2a | ||
|
|
75c35c4ff8 | ||
|
|
9d573512d0 | ||
|
|
7921365853 | ||
|
|
43263fd3b9 | ||
|
|
59042a5ead | ||
|
|
91b14de807 | ||
|
|
81fab2be08 | ||
|
|
165b742782 | ||
|
|
76fef9c807 | ||
|
|
e69ea0b9dc | ||
|
|
98d3183f2b | ||
|
|
a29390a951 | ||
|
|
6291ce8617 | ||
|
|
c76b1b50a0 | ||
|
|
cc45e2aec0 | ||
|
|
17efebb8e8 | ||
|
|
5c94c733ee | ||
|
|
156b89dd9c | ||
|
|
34ba9f67e7 | ||
|
|
5ddaa6b872 | ||
|
|
9043fa7f56 | ||
|
|
4c8e487dc9 | ||
|
|
d3b87179aa | ||
|
|
2166de8331 | ||
|
|
f0bc3f001f | ||
|
|
50448e7085 | ||
|
|
cd1d42353e | ||
|
|
5e588bf737 | ||
|
|
7ff777d178 | ||
|
|
861621189a | ||
|
|
dcc00e08fd | ||
|
|
a1b8a47d4b | ||
|
|
1fd6b5e239 | ||
|
|
f91e45bf44 | ||
|
|
0675a45592 | ||
|
|
0c7c6ae451 | ||
|
|
cf089e8c4c | ||
|
|
90928ac679 | ||
|
|
3bbcf71784 | ||
|
|
222734775d | ||
|
|
f23ee7a6e0 | ||
|
|
5b075aa6d5 | ||
|
|
80cd6b693e | ||
|
|
04721a12b1 | ||
|
|
64e22c0e46 | ||
|
|
d5a70c5b08 | ||
|
|
eaac7b6bcf | ||
|
|
b062a491cd | ||
|
|
1e868517bb | ||
|
|
7b2a93a2d7 | ||
|
|
f57f0447c6 | ||
|
|
7126ff881e | ||
|
|
e28da4b165 | ||
|
|
92d9b91f7c | ||
|
|
149c4a30c0 | ||
|
|
84e62062ec | ||
|
|
dc1fb74850 | ||
|
|
00c6010789 | ||
|
|
5d35c058e0 | ||
|
|
1522a521f6 | ||
|
|
6e11b885f9 | ||
|
|
442ae6e0e8 | ||
|
|
6b49e83464 | ||
|
|
f1ecf13fe1 | ||
|
|
83d1c8582b | ||
|
|
179f6cd454 | ||
|
|
91b1474ff0 | ||
|
|
15aabc88a1 | ||
|
|
afc0d3017d | ||
|
|
9e0b1dc8aa | ||
|
|
55b482fd26 | ||
|
|
4f9c9a6566 | ||
|
|
4725120ee9 | ||
|
|
a288f50fbb | ||
|
|
09cf2560a4 | ||
|
|
16353de7b1 | ||
|
|
eb5834cb5c | ||
|
|
3ef5736aed | ||
|
|
d2e7b77d16 | ||
|
|
8f794bce75 | ||
|
|
c33196a50a | ||
|
|
6e8b5b431f | ||
|
|
8ca3ecf17f | ||
|
|
91f7db59ea | ||
|
|
a0b4501352 | ||
|
|
345047820a | ||
|
|
ac3525a953 | ||
|
|
c8c3f5b134 | ||
|
|
51319c0718 | ||
|
|
43399b8b47 | ||
|
|
a6596042b7 | ||
|
|
23ae85fc9c | ||
|
|
2da54862f1 | ||
|
|
f272fb0559 | ||
|
|
bd04e33586 | ||
|
|
b09b9752ca | ||
|
|
a810a48158 | ||
|
|
b4f5792aa8 | ||
|
|
fdf0330b4f | ||
|
|
ca73743082 | ||
|
|
df0cde2cfd | ||
|
|
5a8421e807 | ||
|
|
025ac95d81 | ||
|
|
71b5824fdc | ||
|
|
1a907c0be7 | ||
|
|
1635cabd32 | ||
|
|
27946a5b0f | ||
|
|
e141822fd0 | ||
|
|
6326828a02 | ||
|
|
96b5362491 | ||
|
|
8ab91a51bc | ||
|
|
35e7e7af18 | ||
|
|
0e248a7302 | ||
|
|
d5ce4d6600 | ||
|
|
2365bb5e87 | ||
|
|
2230216a7e | ||
|
|
54f896d25f | ||
|
|
e47d239caf | ||
|
|
ac259958d7 | ||
|
|
0505ad88a6 | ||
|
|
b323de3383 | ||
|
|
c0e023324b | ||
|
|
495806d5e3 | ||
|
|
3a9f745a2d | ||
|
|
7b15d114a3 | ||
|
|
6ac0f72169 | ||
|
|
ff68030231 | ||
|
|
d34361b6dd | ||
|
|
56c6ebe523 | ||
|
|
2c6d2e0eb4 | ||
|
|
8e64196a8f | ||
|
|
926d5faf21 | ||
|
|
18bad2af25 | ||
|
|
6be4dc4aac | ||
|
|
6398a59dda | ||
|
|
48158b1db6 | ||
|
|
47fe519e54 | ||
|
|
7e06f19bbc | ||
|
|
0b66c1f0d6 | ||
|
|
ff2742ffd8 | ||
|
|
70c2992a5f | ||
|
|
4ac4ee6874 | ||
|
|
865164a404 | ||
|
|
f9c8069ab2 | ||
|
|
2fbf5140e5 | ||
|
|
0126f8144a | ||
|
|
71383d7482 | ||
|
|
4d3bfc5f42 | ||
|
|
c173d217de | ||
|
|
d2da9a039f | ||
|
|
c915edd458 | ||
|
|
504948452e | ||
|
|
3daa6c7a54 | ||
|
|
10cd1580a5 | ||
|
|
5b0876e106 | ||
|
|
cfcdeaff01 | ||
|
|
7c34f233fd | ||
|
|
686146a7d9 | ||
|
|
44732d5977 | ||
|
|
05c3794cf7 | ||
|
|
f0431a504a | ||
|
|
eccec85ea6 | ||
|
|
16ff538804 | ||
|
|
f81e07eb6f | ||
|
|
1cbd41ad87 | ||
|
|
d8567b8427 | ||
|
|
afe6a1923b | ||
|
|
0f60f4754f | ||
|
|
7e988d0401 | ||
|
|
d85813c229 | ||
|
|
12eb56809d | ||
|
|
d792172779 | ||
|
|
011562ae73 | ||
|
|
71c4e36933 | ||
|
|
6261982f6c | ||
|
|
4ac01e0ed0 | ||
|
|
2dfe07f13e | ||
|
|
7f4e4017ce | ||
|
|
635970f37b | ||
|
|
106e740220 | ||
|
|
3e6420ba6f | ||
|
|
79be8010d5 | ||
|
|
0b6e679f3b | ||
|
|
97c43ad2b9 | ||
|
|
cbf978745c | ||
|
|
63dceada90 | ||
|
|
366aade8b4 | ||
|
|
aeb505e3d9 | ||
|
|
f9482e4773 | ||
|
|
57dfc22ff7 | ||
|
|
adc489b6ed | ||
|
|
0623684315 | ||
|
|
68afccd859 | ||
|
|
99eef8fb28 | ||
|
|
47e7685d39 | ||
|
|
b6ea596ade | ||
|
|
44d60b469b | ||
|
|
51087408df | ||
|
|
96226d9e6e | ||
|
|
28f0f62424 | ||
|
|
2e772a8cd4 | ||
|
|
3fd192f0cf | ||
|
|
d16ae81961 | ||
|
|
211a8e093e | ||
|
|
84010a51d6 | ||
|
|
e9700ea19b | ||
|
|
e81ec68072 | ||
|
|
6096e97708 | ||
|
|
6f302b66b4 | ||
|
|
b6e41890f7 | ||
|
|
be5332a048 | ||
|
|
4d72aeb0cd | ||
|
|
c7c3c35100 | ||
|
|
2f0df3c552 | ||
|
|
e6effcd921 | ||
|
|
cd462b9523 | ||
|
|
7e2e17d38b | ||
|
|
665d616a06 | ||
|
|
ced90f5bb9 | ||
|
|
ca0ddb6cb4 | ||
|
|
3d733813e1 | ||
|
|
45ddc0b154 | ||
|
|
87294497f3 | ||
|
|
5f45f9c0d0 | ||
|
|
7f78c06793 | ||
|
|
8ea5b7eebc | ||
|
|
e49cd511af | ||
|
|
15c88646df | ||
|
|
f47919543d | ||
|
|
a95291d9cd | ||
|
|
033deb3d29 | ||
|
|
923994c1f4 | ||
|
|
3d45b839b4 | ||
|
|
55d1efa212 | ||
|
|
21d794a0e5 | ||
|
|
614022a78c | ||
|
|
c00688e23a | ||
|
|
5c69917d19 | ||
|
|
6a5eb75b6c | ||
|
|
727c55eaa2 | ||
|
|
9b03173ec5 | ||
|
|
ab95855d6d | ||
|
|
bb84594c6b | ||
|
|
97392c76b1 | ||
|
|
53aec2b306 | ||
|
|
a0a381dc63 | ||
|
|
4fa95edeec | ||
|
|
b944f1d70e | ||
|
|
0f1a5d0085 | ||
|
|
e7e10222e7 | ||
|
|
87c4fda588 | ||
|
|
0ff820de6f | ||
|
|
0dcf55e6d9 | ||
|
|
a69842c910 | ||
|
|
318f635e4d | ||
|
|
abf0d72316 | ||
|
|
5cd89c8844 | ||
|
|
501c1af38c | ||
|
|
8526e130d9 | ||
|
|
76fd08eade | ||
|
|
bfe48ae9d2 | ||
|
|
8547cdba7c | ||
|
|
00d0cd631d | ||
|
|
04460d13cd | ||
|
|
a17a15e5d7 | ||
|
|
bfe2465658 | ||
|
|
4568987785 | ||
|
|
c0e5a1419d | ||
|
|
23ac7ab748 | ||
|
|
5622dc74a8 | ||
|
|
528986f4f0 | ||
|
|
e6b8ff3f91 | ||
|
|
3fc3c5296f | ||
|
|
f4f2a14a31 | ||
|
|
fa3f464cb6 | ||
|
|
bed20538ae | ||
|
|
3da461c6e6 | ||
|
|
9c73e8452a | ||
|
|
750dab69d3 | ||
|
|
702d0da47c | ||
|
|
3a955b1e53 | ||
|
|
d408bd93e8 | ||
|
|
63fd9eb1de | ||
|
|
4718ab6ddf | ||
|
|
affd4b3a26 | ||
|
|
6a660dbcda | ||
|
|
5ff3af8b48 | ||
|
|
9d49070f93 | ||
|
|
5b3994a1dd | ||
|
|
bb1e62c580 | ||
|
|
29cc776908 | ||
|
|
d2ef60b2ec | ||
|
|
41ea496d41 | ||
|
|
c69bb38929 | ||
|
|
23b3f8494e | ||
|
|
0ff94eec1b | ||
|
|
f67a638565 | ||
|
|
778cf71c61 | ||
|
|
e2da083b48 | ||
|
|
dcc48c0d4b | ||
|
|
2446b4a591 | ||
|
|
a973d633c8 | ||
|
|
c3b11e6e0f | ||
|
|
44bec2d99e | ||
|
|
0d59d0a3f6 | ||
|
|
ddc8372b09 | ||
|
|
ea7325f4e0 | ||
|
|
6048f95415 | ||
|
|
5682705b8d | ||
|
|
6c3b82607d | ||
|
|
486c9f4ebf | ||
|
|
7c8adebf2d | ||
|
|
ce98bb0dc1 | ||
|
|
60b49a4296 | ||
|
|
5d0a2ffae0 | ||
|
|
bbcf7c722a | ||
|
|
66574eec6d | ||
|
|
305df3a42c | ||
|
|
323c6f4270 | ||
|
|
c056b2b14c | ||
|
|
02ebb07fd8 | ||
|
|
59db0890c3 | ||
|
|
3ea0d9ed3a | ||
|
|
0371d11dd5 | ||
|
|
12f1ebaee9 | ||
|
|
5202cc22d1 | ||
|
|
07a34bdcbf | ||
|
|
27806da4be | ||
|
|
a15dd1a3ce | ||
|
|
6cc7451c7c | ||
|
|
652aeee782 | ||
|
|
8e1e887b8f | ||
|
|
6601a2de64 | ||
|
|
75a42ffc32 | ||
|
|
8a80a52f5f | ||
|
|
b373a434ba | ||
|
|
cd78fdafe6 | ||
|
|
7a1b4c6db7 | ||
|
|
f2c7664033 | ||
|
|
12b295f067 | ||
|
|
3ee46da40f | ||
|
|
beadaa7212 | ||
|
|
16ef09426f | ||
|
|
b8c1f1f5a9 | ||
|
|
e027b5cbd6 | ||
|
|
bf1bd73ad1 | ||
|
|
86fc95119a | ||
|
|
b3a76ea17b | ||
|
|
bababd9d53 | ||
|
|
8cd5180531 | ||
|
|
f1ccbade8c | ||
|
|
a66f4b0417 | ||
|
|
ff495b2261 | ||
|
|
90e5824212 | ||
|
|
3d64021062 | ||
|
|
fb8ed7428d | ||
|
|
bdc273c10a | ||
|
|
2d96cffdc7 | ||
|
|
4356fccbcd | ||
|
|
a169fd4ce7 | ||
|
|
dcd418139e | ||
|
|
0cac2062d3 | ||
|
|
854c5d4ade | ||
|
|
0f96c6ec84 | ||
|
|
b219bd66c1 | ||
|
|
cb52f2c0b3 | ||
|
|
d3273e03ef | ||
|
|
afbfd963f3 | ||
|
|
2cd101c5f3 | ||
|
|
b10bc24dee | ||
|
|
51a23df861 | ||
|
|
03a0a9dad9 | ||
|
|
362c0affbe | ||
|
|
d5b523479f | ||
|
|
7719b8f6d7 | ||
|
|
3656c0d524 | ||
|
|
8b9e0dd6ea | ||
|
|
b3921b1037 | ||
|
|
d7d96e5dbf | ||
|
|
3934395b7b | ||
|
|
04fbe9a529 | ||
|
|
badd6dd9a2 | ||
|
|
059082456d | ||
|
|
405b68e22f | ||
|
|
c90bf6692c | ||
|
|
b5ea5d0cc5 | ||
|
|
243617a1e1 | ||
|
|
9e703edd59 | ||
|
|
d6c2cf2810 | ||
|
|
ae7811acfa | ||
|
|
e55731c099 | ||
|
|
9df5c74da4 | ||
|
|
8b75f9f785 | ||
|
|
bf12428cf4 | ||
|
|
b551df978b | ||
|
|
c91d85d2f0 | ||
|
|
965237fa1f | ||
|
|
24cd9afc06 | ||
|
|
602fdefebd | ||
|
|
7e7818aa17 | ||
|
|
27a6023a6a | ||
|
|
3861879900 | ||
|
|
807eeb8351 | ||
|
|
045fa53d58 | ||
|
|
69d405ece7 | ||
|
|
d3dc4d0c5b | ||
|
|
7beba1188e | ||
|
|
9779ebe12c | ||
|
|
f72cfaa093 | ||
|
|
cf8ccafb4a | ||
|
|
7fe281b0b8 | ||
|
|
5f70e9574f | ||
|
|
4be51923ba | ||
|
|
a72c78f4a4 | ||
|
|
b4d32a6de1 | ||
|
|
8a6b2d5daa | ||
|
|
bebadeef14 | ||
|
|
3551be67f0 | ||
|
|
1103950b25 | ||
|
|
9d06e01cec | ||
|
|
24be946b7e | ||
|
|
f56d2fc60f | ||
|
|
9f8356f409 | ||
|
|
8e6345d938 | ||
|
|
0eac78bd1c | ||
|
|
21db2502d0 | ||
|
|
38c3492123 | ||
|
|
6376bff476 | ||
|
|
38495a3ebc | ||
|
|
cf00897be2 | ||
|
|
da640f24ec | ||
|
|
ed6a777c42 | ||
|
|
81af4485d3 | ||
|
|
94d8f0237d | ||
|
|
c5e579dd38 | ||
|
|
7865e76ee2 | ||
|
|
4d37212cc0 | ||
|
|
9ca43f0bb4 | ||
|
|
fe8d262175 | ||
|
|
493d6e7165 | ||
|
|
17b630bcd8 | ||
|
|
018c5ad3b4 | ||
|
|
a14b4da977 | ||
|
|
01b4597cc7 | ||
|
|
0b083ccc1c | ||
|
|
ca22cb0eae | ||
|
|
bcbb8e5f8c | ||
|
|
bea286cdd4 | ||
|
|
892d2ee8d2 | ||
|
|
7440608c14 | ||
|
|
6246f0295b | ||
|
|
53c39d9b43 | ||
|
|
9a50b60031 | ||
|
|
fd74527320 | ||
|
|
f91fb522ac | ||
|
|
7019c02b18 | ||
|
|
94f8422b9b | ||
|
|
b25c01567a | ||
|
|
b9329885de | ||
|
|
ac88c4cff9 | ||
|
|
9674f2d238 | ||
|
|
38c9ecb6f1 | ||
|
|
be9e9cdd5a | ||
|
|
afdaf07446 | ||
|
|
5caaf10225 | ||
|
|
daffc3a776 | ||
|
|
34c9748ce5 | ||
|
|
f17acbf4d1 | ||
|
|
229f56ce2f | ||
|
|
0847bedc51 | ||
|
|
9e4546c305 | ||
|
|
97b01bf26a | ||
|
|
e7011628d0 | ||
|
|
044ffdecbd | ||
|
|
1a06a3543b | ||
|
|
5fedc0bf1e | ||
|
|
7a881f867e | ||
|
|
dfe73a6cfb | ||
|
|
45d0fb27ad | ||
|
|
31890af61d | ||
|
|
a54b3ecc15 | ||
|
|
c37cd1bd51 | ||
|
|
0e3ee89cbf | ||
|
|
a049176c14 | ||
|
|
5ef2b0089e | ||
|
|
1cc4899593 | ||
|
|
26d1390be9 | ||
|
|
dc65584fb3 | ||
|
|
b3d5a708d5 | ||
|
|
904a5d296b | ||
|
|
cc82e6a47a | ||
|
|
a9d02ec854 | ||
|
|
6b5a2d3767 | ||
|
|
10d9060b94 | ||
|
|
8441839c01 | ||
|
|
b669f5838f | ||
|
|
1a942f9ce1 | ||
|
|
ae840758f7 | ||
|
|
082c08e5f9 | ||
|
|
74a43557ab | ||
|
|
184271789d | ||
|
|
fa61b0cad8 | ||
|
|
7b197a90d1 | ||
|
|
62384af2f6 | ||
|
|
b466202a1a | ||
|
|
7ab38c18d8 | ||
|
|
39841ee43e | ||
|
|
e419800d98 | ||
|
|
63c99ab69a | ||
|
|
e2a8fd2279 | ||
|
|
bbde520471 | ||
|
|
45fb12f98e | ||
|
|
4be3dcce50 | ||
|
|
d12a41c769 | ||
|
|
ed9a58c9ed | ||
|
|
4389cea5a1 | ||
|
|
d24854920b | ||
|
|
9902443bee | ||
|
|
8040b2ef16 | ||
|
|
4533680b10 | ||
|
|
3b28175135 | ||
|
|
8e22812265 | ||
|
|
409bc91b9e | ||
|
|
61fe543a2a | ||
|
|
8a949a7e64 | ||
|
|
b0dc9fb97a | ||
|
|
83114d1002 | ||
|
|
94a25a903f | ||
|
|
4f402f9e55 | ||
|
|
27bb2e3dcc | ||
|
|
66cc52f6ec | ||
|
|
ed1367b116 | ||
|
|
5c055352e4 | ||
|
|
8dcff5ada1 | ||
|
|
4b8b23d7d5 | ||
|
|
e576f6aed3 | ||
|
|
97ab04da91 | ||
|
|
c6361bb36e | ||
|
|
b0b3dc225d | ||
|
|
9cbaba192a | ||
|
|
f511598e13 | ||
|
|
5ffff3b7aa | ||
|
|
24c4fa1c4f | ||
|
|
7f312c1273 | ||
|
|
ef5c226c81 | ||
|
|
3f029cf799 | ||
|
|
5bf64a8bec | ||
|
|
89f9c537f8 | ||
|
|
e8d7f57818 | ||
|
|
9b42fa78e7 | ||
|
|
96d98e8f39 | ||
|
|
1f3a281e78 | ||
|
|
dab4b66ee0 | ||
|
|
64dd192ddb | ||
|
|
b0a5c383d0 | ||
|
|
4836cc99eb | ||
|
|
ba33873354 | ||
|
|
12c838cab0 | ||
|
|
a83a1c83a7 | ||
|
|
2234f47170 | ||
|
|
4bae1b17fc | ||
|
|
6a7a0e0fa6 | ||
|
|
bff987c55f | ||
|
|
e467006913 | ||
|
|
1d646d4a6d | ||
|
|
70bd4936a1 | ||
|
|
5ae7add6d2 | ||
|
|
02b206ce7c | ||
|
|
2ea626a567 | ||
|
|
653909ec11 | ||
|
|
1d7c148eaf | ||
|
|
94a7e130ca | ||
|
|
609abacdf0 | ||
|
|
033ff2e49a | ||
|
|
00a9bf0641 | ||
|
|
100f322456 | ||
|
|
2251e08d30 | ||
|
|
14e9beef53 | ||
|
|
c7cce23d54 | ||
|
|
7becf32352 | ||
|
|
741eda9f4e | ||
|
|
473f51481c | ||
|
|
684f9bd11b | ||
|
|
b4b7f0c360 | ||
|
|
cf42d02628 | ||
|
|
cc9a9eab7b | ||
|
|
784d6abc9b | ||
|
|
0eafc07184 | ||
|
|
7e9499bd2e | ||
|
|
d01a52aa95 | ||
|
|
6bcd492980 | ||
|
|
96b15da04b | ||
|
|
e0f1801693 | ||
|
|
d195ad85c5 | ||
|
|
773f7b6c1b | ||
|
|
40f29fe399 | ||
|
|
b19eb117c1 | ||
|
|
f930ba5eff | ||
|
|
fbbda6c230 | ||
|
|
47db4968e5 | ||
|
|
1aff2e518c | ||
|
|
24134ca49e | ||
|
|
aadbe05a5e | ||
|
|
18eddf4700 | ||
|
|
0869ba7e70 | ||
|
|
cba5db1c53 | ||
|
|
0aa5430e23 | ||
|
|
88a91828cb | ||
|
|
27af89f5fe | ||
|
|
6f6d483bfe | ||
|
|
915072c191 | ||
|
|
76077b92ae | ||
|
|
f0d1a527a5 | ||
|
|
fdb2a96d1c | ||
|
|
849e3ac187 | ||
|
|
5c4cf21c59 | ||
|
|
40ee3e5d9b | ||
|
|
77a7cc034e | ||
|
|
82b7881765 | ||
|
|
3515775267 | ||
|
|
10e12aa1c1 | ||
|
|
7fb4e62aa3 | ||
|
|
2605eaa614 | ||
|
|
8e97b4820d | ||
|
|
89af4cdb68 | ||
|
|
6099c1a25a | ||
|
|
fd23758aea | ||
|
|
8ad0b89db1 | ||
|
|
e7dffa3ff4 | ||
|
|
2772b5d2e2 | ||
|
|
df6d9b5f70 | ||
|
|
c9622d6d57 | ||
|
|
1f0b7c3c7e | ||
|
|
c12245037e | ||
|
|
fe6d2a50a5 | ||
|
|
7be84950f8 | ||
|
|
ba212da222 | ||
|
|
122b833256 | ||
|
|
7c73479041 | ||
|
|
151f2e99ae | ||
|
|
da367e813f | ||
|
|
9143dfe336 | ||
|
|
29914d6a72 | ||
|
|
0dbef72a97 | ||
|
|
3bb118bfe1 | ||
|
|
85ce3be077 | ||
|
|
064c2bf0a8 | ||
|
|
c96d06ccc5 | ||
|
|
a658dbb753 | ||
|
|
bf5d5b629e | ||
|
|
241d576519 | ||
|
|
7807e9bdd0 | ||
|
|
fcbf15fed6 | ||
|
|
cd90a11209 | ||
|
|
ff65707ea2 | ||
|
|
b16026070c | ||
|
|
1b5fbf86d8 | ||
|
|
5eb1be8101 | ||
|
|
6a863cd26a | ||
|
|
87ebb7b6c7 | ||
|
|
1233a74307 | ||
|
|
221890acfb | ||
|
|
687c7e766e | ||
|
|
ba22c407d3 | ||
|
|
a8b9ed56b5 | ||
|
|
3004869e19 | ||
|
|
1145853fe1 | ||
|
|
f1617a25b1 | ||
|
|
932be558d9 | ||
|
|
ee3a37d3b9 | ||
|
|
5ac412a582 | ||
|
|
1625290bc3 | ||
|
|
1ec169ad49 | ||
|
|
53be552e44 | ||
|
|
d3a75d46b9 | ||
|
|
256512c961 | ||
|
|
5c12ac5bcc | ||
|
|
02a2bcb113 | ||
|
|
1f0a01c725 | ||
|
|
6ea164ede1 | ||
|
|
65bae85ecc | ||
|
|
2fd7dcf4d0 | ||
|
|
aa3bbbe038 | ||
|
|
6cb09a6f95 | ||
|
|
45868f05d3 | ||
|
|
aac7401e20 | ||
|
|
c2fc290edd | ||
|
|
330357fc36 | ||
|
|
f4a3d6a64e | ||
|
|
2e0963ec81 | ||
|
|
897cb6e62a | ||
|
|
80868bd48e | ||
|
|
b3df78c56f | ||
|
|
783a4259e3 | ||
|
|
fcf19b8dc8 | ||
|
|
1f9f89817d | ||
|
|
7b94da7d85 | ||
|
|
164406f6c2 | ||
|
|
90ef2adc6b | ||
|
|
d65f10f88b | ||
|
|
dca0ece9e0 | ||
|
|
baabc155c8 | ||
|
|
7eb94412d6 | ||
|
|
0fc8b24f85 | ||
|
|
88f6ef5b96 | ||
|
|
7442483419 | ||
|
|
9c61933c04 | ||
|
|
2b36a99720 | ||
|
|
c2cfc42ba4 | ||
|
|
4f32704e08 | ||
|
|
fccf43685f | ||
|
|
39135d81ad | ||
|
|
ff4b10681e | ||
|
|
10b7908fc2 | ||
|
|
31790da8c6 | ||
|
|
4621201c47 | ||
|
|
692ac31dbf | ||
|
|
ed1d163d55 | ||
|
|
e931c9040c | ||
|
|
f23cb48ea4 | ||
|
|
c3b2b6b07b | ||
|
|
f89bf590ba | ||
|
|
fea17dc00b | ||
|
|
dbb1069920 | ||
|
|
afc4ccfaa9 | ||
|
|
38d55a1c07 | ||
|
|
5fca29f103 | ||
|
|
78f34b2ca4 | ||
|
|
8e8028e809 | ||
|
|
8dc70687f8 | ||
|
|
fa22f9ee64 | ||
|
|
b33c0d3f81 | ||
|
|
339009add4 | ||
|
|
798c823c4b | ||
|
|
14ad86f2a3 | ||
|
|
a3a714dc17 | ||
|
|
e8d8b0d41d | ||
|
|
17daad8f89 | ||
|
|
e178263b3b | ||
|
|
4febbc261e | ||
|
|
ef3a6942fd | ||
|
|
f8ac2be62b | ||
|
|
25447c34e5 | ||
|
|
37cdf8fd48 | ||
|
|
ac8e7dc959 | ||
|
|
8293382840 | ||
|
|
d85a3e7743 | ||
|
|
f3f5ffb5c8 | ||
|
|
99e6702c62 | ||
|
|
e143c25078 | ||
|
|
3fb67972be | ||
|
|
61c04d4e09 | ||
|
|
b22f728958 | ||
|
|
112be7e383 | ||
|
|
6a7f83fed5 | ||
|
|
4b9698a735 | ||
|
|
ec3d203a6d | ||
|
|
e77b8f5475 | ||
|
|
da8bbd321f | ||
|
|
98fd011def | ||
|
|
9dccbc5316 | ||
|
|
03fa26daf9 | ||
|
|
fbc41e3895 | ||
|
|
f1a6d0c02c | ||
|
|
67f6bb7155 | ||
|
|
86282f596c | ||
|
|
e0f24c795c | ||
|
|
7d44ed860c | ||
|
|
091094a24c | ||
|
|
ba18ee518c | ||
|
|
513a031691 | ||
|
|
cc79de1106 | ||
|
|
bd90e8efb2 | ||
|
|
4bd88ff11d | ||
|
|
d27ee61292 | ||
|
|
0c20b3345f | ||
|
|
0f3c8c7193 | ||
|
|
16761ec605 | ||
|
|
1069440cda | ||
|
|
60f5702f17 | ||
|
|
ee70133e47 | ||
|
|
06a9fdeb2e | ||
|
|
f14bd62004 | ||
|
|
67cbaf22b7 | ||
|
|
60b166dba2 | ||
|
|
66e1647ede | ||
|
|
a1a35c00a5 | ||
|
|
b02e3361c4 | ||
|
|
2b9ceaa25a | ||
|
|
109b5a9755 | ||
|
|
cc4df86c10 | ||
|
|
e93532c395 | ||
|
|
6ff688326a | ||
|
|
eda5d2872f | ||
|
|
dc88394f5f | ||
|
|
ec85c9a2c6 | ||
|
|
1341638556 | ||
|
|
4875dfee11 | ||
|
|
d834ba8bd4 | ||
|
|
6191067771 | ||
|
|
6c3a571163 | ||
|
|
5efb07e10e | ||
|
|
b25ec18ce6 | ||
|
|
f3cd281241 | ||
|
|
58b93cbf4c | ||
|
|
57fc0349ff | ||
|
|
d0a2cea772 | ||
|
|
58d5801fb5 | ||
|
|
e5f2e59798 | ||
|
|
1166921057 | ||
|
|
aeb49576f2 | ||
|
|
7ef1fecef8 | ||
|
|
fd630373b5 | ||
|
|
d365d8f170 | ||
|
|
dfa5e1172f | ||
|
|
daf195898a | ||
|
|
c61c0a39cf | ||
|
|
6137e6baa5 | ||
|
|
fd16fd9ffe | ||
|
|
2b8bd5f2cc | ||
|
|
d312c2e9e7 | ||
|
|
578b0d2268 | ||
|
|
ffb41b0109 | ||
|
|
c63fb5d796 | ||
|
|
8caee732e8 | ||
|
|
df5381adce | ||
|
|
f34836b7fa | ||
|
|
44b459883a | ||
|
|
14a8592ae3 | ||
|
|
787d0dce4a | ||
|
|
8be05ff93d | ||
|
|
3014af565c | ||
|
|
315252bdc4 | ||
|
|
c36c3b4607 | ||
|
|
7d5e939bab | ||
|
|
f75c9d1eed | ||
|
|
38cb9855ea | ||
|
|
ed8b56d624 | ||
|
|
bca48b13ae | ||
|
|
29426edb05 | ||
|
|
33a2dc687f | ||
|
|
e2398a21b2 | ||
|
|
f19530276e | ||
|
|
2b9b92a78c | ||
|
|
99c55dac10 | ||
|
|
25667e46f9 | ||
|
|
2f4e8f2399 | ||
|
|
9169183769 | ||
|
|
c420f50831 | ||
|
|
c6c9279ef4 | ||
|
|
c125e2991d | ||
|
|
5348b19d6a | ||
|
|
afd426daac | ||
|
|
202c511cfa | ||
|
|
651eb295a4 | ||
|
|
d798aaed33 | ||
|
|
63ef347cc9 | ||
|
|
3139b2d5a0 | ||
|
|
2c80bbb244 | ||
|
|
af06755ada | ||
|
|
97d6dbaa6c | ||
|
|
74cf82a1c7 | ||
|
|
74634889ab | ||
|
|
dbe30fcd77 | ||
|
|
24a7f3a320 | ||
|
|
d3650f1145 | ||
|
|
4801db9050 | ||
|
|
6445281658 | ||
|
|
87719f5938 | ||
|
|
5ba1ec433b | ||
|
|
7c5b382458 | ||
|
|
8960426128 | ||
|
|
e1d47d5a92 | ||
|
|
9407c272aa | ||
|
|
bccbd7b400 | ||
|
|
a24dc010ec | ||
|
|
c5e5d50fb8 | ||
|
|
be1c520320 | ||
|
|
3d18d0f893 | ||
|
|
c3351a38a6 | ||
|
|
0b86340a8d | ||
|
|
829371b032 | ||
|
|
b342207bc7 | ||
|
|
58f4fdced3 | ||
|
|
253844cbcf | ||
|
|
e2e2b9ffb4 | ||
|
|
2568042f5f | ||
|
|
722edf4b9a | ||
|
|
e406d364e4 | ||
|
|
31c37f41b2 | ||
|
|
6cd879bbc5 | ||
|
|
b7974050fe | ||
|
|
e9c9d0816e | ||
|
|
a437692e1a | ||
|
|
2a14d2f3c8 | ||
|
|
559e2d1889 | ||
|
|
a1aa919f80 | ||
|
|
cbccb27a5a | ||
|
|
bbad36d576 | ||
|
|
df6c9d55b5 | ||
|
|
36a1d9c364 | ||
|
|
1f3681d5ac | ||
|
|
0159f8e53f | ||
|
|
0432be64fc | ||
|
|
481e062961 | ||
|
|
72b8abdeb6 | ||
|
|
7ec3ee41d1 | ||
|
|
b765fa4769 | ||
|
|
06685b162e | ||
|
|
7bcad7c424 | ||
|
|
6e054b3cc6 | ||
|
|
e643f6b0f8 | ||
|
|
e44c0f85c2 | ||
|
|
ea66e968eb | ||
|
|
f7e73d804e | ||
|
|
2ff4df56a1 | ||
|
|
346c45fe0c | ||
|
|
f98b42a36e | ||
|
|
f77a0a266c | ||
|
|
0be672788f | ||
|
|
e2e3d11d42 | ||
|
|
bb127bb567 | ||
|
|
8eb4f89db8 | ||
|
|
4a87ea3e70 | ||
|
|
61115fce99 | ||
|
|
4f31120394 | ||
|
|
b085cd65ce | ||
|
|
f76ec0721a | ||
|
|
ef3944fbbf | ||
|
|
b158fbc0d8 | ||
|
|
68f2d66e97 | ||
|
|
0cdd1735bd | ||
|
|
70f5ead20b | ||
|
|
574e5616f8 | ||
|
|
94fa810590 | ||
|
|
37f69da701 | ||
|
|
f2f8448ade | ||
|
|
b357d3fff2 | ||
|
|
b417194905 | ||
|
|
d8741da20a | ||
|
|
c469be9a62 | ||
|
|
ff4eb339ef | ||
|
|
78489383c0 | ||
|
|
f67c1b415f | ||
|
|
570c16d921 | ||
|
|
c8bc60568a | ||
|
|
73de3ba856 | ||
|
|
6a69be8537 | ||
|
|
3ee381d505 | ||
|
|
7ce744e2e4 | ||
|
|
b81d21c991 | ||
|
|
e9fe0992c6 | ||
|
|
d5ef9018fa | ||
|
|
c2737a7c51 | ||
|
|
4b6d8733c6 | ||
|
|
f22a3e0955 | ||
|
|
4b8144a2f7 | ||
|
|
abac52e23c | ||
|
|
9aa089313e | ||
|
|
b18f2c481a | ||
|
|
ec83b9f77b | ||
|
|
fad5495e02 | ||
|
|
70dec1171e | ||
|
|
0673a6fce3 | ||
|
|
8f525b1407 | ||
|
|
e83a991a4b | ||
|
|
c000432a52 | ||
|
|
c06d2d6927 | ||
|
|
aa29653a8f | ||
|
|
3f7e4ad486 | ||
|
|
0eab546b2f | ||
|
|
8830d216d1 | ||
|
|
9fa1e3d449 | ||
|
|
fe5dce7159 | ||
|
|
952fa31548 | ||
|
|
cc058ccc61 | ||
|
|
bc26ed9701 | ||
|
|
26135fc1a0 | ||
|
|
0bd14672ff | ||
|
|
7c7150cde8 | ||
|
|
b08282b0c1 | ||
|
|
3bf6e1befc | ||
|
|
52692371ac | ||
|
|
159ac1d8bb | ||
|
|
7f1ffdbc79 | ||
|
|
5fe64931dc | ||
|
|
ee67855b48 | ||
|
|
594a97f43f | ||
|
|
7fb435a8b4 | ||
|
|
01e74d6116 | ||
|
|
b321d75b39 | ||
|
|
1e47a45723 | ||
|
|
88c609e5ef | ||
|
|
775d1a424e |
63
.gitattributes
vendored
63
.gitattributes
vendored
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -360,7 +360,4 @@ MigrationBackup/
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
|
||||
/framework/*Pro*
|
||||
FodyWeavers.xsd
|
||||
@@ -87,7 +87,7 @@
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
4. Cachetribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
111
README.md
111
README.md
@@ -1,38 +1,95 @@
|
||||
|
||||
# ThingsGateway
|
||||
|
||||
## 介绍
|
||||
|
||||
|
||||
**NetCore** 跨平台边缘采集网关(工业设备采集)
|
||||
## Introduction
|
||||
|
||||
**ThingsGateway** 存储库同时提供 [**设备采集驱动**](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
|
||||
|
||||
A cross-platform, high-performance edge data collection gateway based on net8, capable of handling millions of data points per.
|
||||
|
||||
|
||||
**ThingsGateway** 存储库同时提供 **基于Blazor的权限框架** 查看 **ThingsGateway - Admin**
|
||||
## Documentation
|
||||
|
||||
|
||||
[Documentation](https://thingsgateway.cn/).
|
||||
|
||||
[NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
|
||||
|
||||
|
||||
### Plugin List
|
||||
|
||||
|
||||
|
||||
#### Data Collection Plugins
|
||||
|
||||
|
||||
## 文档
|
||||
| Plugin Name | Remarks |
|
||||
| ----------- | ------------------------------------------------------------- |
|
||||
| Modbus | Supports Rtu/Tcp message formats, with Serial/Tcp/Udp links |
|
||||
| SiemensS7 | Siemens PLC S7 series |
|
||||
| Dlt6452007 | Supports Serial/Tcp/Udp links |
|
||||
| OpcDaMaster | Compiled for 64-bit |
|
||||
| OpcUaMaster | Supports certificate login, object extension, Json read/write |
|
||||
|
||||
[ThingsGateway](https://diego2098.gitee.io/thingsgateway-docs/) 文档。
|
||||
|
||||
## 协议
|
||||
|
||||
[ThingsGateway](https://gitee.com/diego2098/ThingsGateway) 采用 [Apache-2.0](https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.zh) 开源协议。
|
||||
|
||||
## 演示
|
||||
|
||||
[ThingsGateway演示地址](http://120.24.62.140:5000/)
|
||||
|
||||
账户 : **superAdmin**
|
||||
|
||||
密码 : **111111**
|
||||
|
||||
## 赞助
|
||||
|
||||
[ThingsGateway赞助途径](https://diego2098.gitee.io/thingsgateway-docs/docs/donate)
|
||||
|
||||
## 社区
|
||||
|
||||
QQ群:605534569
|
||||
#### Business Plugins
|
||||
|
||||
|
||||
| Plugin Name | Remarks |
|
||||
| ---------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| ModbusSlave | Supports Rtu/Tcp message formats, with Serial/Tcp/Udp links, supports Rpc reverse writing |
|
||||
| OpcUaServer | OpcUa server, supports Rpc reverse writing |
|
||||
| MqttClient | Mqtt client, supports Rpc reverse writing, script-customizable upload content |
|
||||
| MqttServer | Mqtt server, supports WebSocket, supports Rpc reverse writing, script-customizable upload content |
|
||||
| KafkaProducer | Script-customizable upload content |
|
||||
| RabbitMQProducer | Script-customizable upload content |
|
||||
| SqlDB | Relational database storage, supports historical storage and real-time data updates |
|
||||
| SqlHistoryAlarm | Alarm historical data relational database storage |
|
||||
| TDengineDB | Time-series database storage |
|
||||
| QuestDB | Time-series database storage |
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
|
||||
[Apache-2.0](https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE)
|
||||
|
||||
|
||||
## Demo
|
||||
|
||||
|
||||
[Demo](http://47.119.161.158:5000/)
|
||||
|
||||
Account: **SuperAdmin**
|
||||
|
||||
Password: **111111**
|
||||
|
||||
**In the upper-right corner, switch to the IoT Gateway module in the personal popup box**
|
||||
|
||||
## Docker
|
||||
|
||||
```shell
|
||||
|
||||
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway
|
||||
|
||||
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Sponsorship
|
||||
|
||||
|
||||
[Sponsorship Approach](https://thingsgateway.cn/docs/1000)
|
||||
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
QQ Group: 605534569 [Jump](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NnBjPO-8kcNFzo_RzSbdICflb97u2O1i&authKey=V1MI3iJtpDMHc08myszP262kDykbx2Yev6ebE4Me0elTe0P0IFAmtU5l7Sy5w0jx&noverify=0&group_code=605534569)
|
||||
|
||||
|
||||
## Pro Plugins
|
||||
|
||||
|
||||
[Plugin List](https://thingsgateway.cn/docs/1001)
|
||||
|
||||
75
README.zh-CN.md
Normal file
75
README.zh-CN.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# ThingsGateway
|
||||
|
||||
## 介绍
|
||||
|
||||
基于net8的跨平台高性能边缘采集网关,单机采集数据点位可达百万
|
||||
|
||||
## 文档
|
||||
|
||||
[文档](https://thingsgateway.cn/)
|
||||
|
||||
[NuGet](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
|
||||
|
||||
### 插件列表
|
||||
|
||||
#### 采集插件
|
||||
|
||||
|
||||
| 插件名称 | 备注 |
|
||||
| ----------- | ------------------------------------- |
|
||||
| Modbus | Rtu/Tcp报文格式,支持串口/Tcp/Udp链路 |
|
||||
| SiemensS7 | 西门子PLC S7系列 |
|
||||
| Dlt6452007 | 支持串口/Tcp/Udp链路 |
|
||||
| OpcDaMaster | 64位编译 |
|
||||
| OpcUaMaster | 支持证书登录,扩展对象,Json读写 |
|
||||
|
||||
#### 业务插件
|
||||
|
||||
|
||||
| 插件名称 | 备注 |
|
||||
| ---------------- | ---------------------------------------------------------- |
|
||||
| ModbusSlave | Rtu/Tcp报文格式,支持串口/Tcp/Udp链路,支持Rpc反写 |
|
||||
| OpcUaServer | OpcUa服务端,支持Rpc反写 |
|
||||
| MqttClient | Mqtt客户端,支持Rpc反写,脚本自定义上传内容 |
|
||||
| MqttServer | Mqtt服务端,支持WebSocket,支持Rpc反写,脚本自定义上传内容 |
|
||||
| KafkaProducer | 脚本自定义上传内容 |
|
||||
| RabbitMQProducer | 脚本自定义上传内容 |
|
||||
| SqlDB | 关系数据库存储,支持历史存储和实时数据更新 |
|
||||
| SqlHistoryAlarm | 报警历史数据关系数据库存储 |
|
||||
| TDengineDB | 时序数据库存储 |
|
||||
| QuestDB | 时序数据库存储 |
|
||||
|
||||
## 协议
|
||||
|
||||
[Apache-2.0](https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE)
|
||||
|
||||
## 演示
|
||||
|
||||
[ThingsGateway演示地址](http://47.119.161.158:5000/)
|
||||
|
||||
账户 : **SuperAdmin**
|
||||
|
||||
密码 : **111111**
|
||||
|
||||
**右上角个人弹出框中,切换到物联网关模块**
|
||||
|
||||
## Docker
|
||||
|
||||
```shell
|
||||
|
||||
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway
|
||||
|
||||
docker pull registry.cn-shenzhen.aliyuncs.com/thingsgateway/thingsgateway_arm64
|
||||
```
|
||||
|
||||
## 赞助
|
||||
|
||||
[赞助途径](https://thingsgateway.cn/docs/1000)
|
||||
|
||||
## 社区
|
||||
|
||||
QQ群:605534569 [跳转](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NnBjPO-8kcNFzo_RzSbdICflb97u2O1i&authKey=V1MI3iJtpDMHc08myszP262kDykbx2Yev6ebE4Me0elTe0P0IFAmtU5l7Sy5w0jx&noverify=0&group_code=605534569)
|
||||
|
||||
## Pro插件
|
||||
|
||||
[插件列表](https://thingsgateway.cn/docs/1001)
|
||||
@@ -1,7 +0,0 @@
|
||||
[*.cs]
|
||||
|
||||
# CA1848: 使用 LoggerMessage 委托
|
||||
dotnet_diagnostic.CA1848.severity = none
|
||||
|
||||
# CA2254: 模板应为静态表达式
|
||||
dotnet_diagnostic.CA2254.severity = suggestion
|
||||
63
framework/.gitattributes
vendored
63
framework/.gitattributes
vendored
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
364
framework/.gitignore
vendored
364
framework/.gitignore
vendored
@@ -1,364 +0,0 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>3.0.0.1</Version>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<Authors>Diego</Authors>
|
||||
<Product>ThingsGateway</Product>
|
||||
<Copyright>© 2023-present Diego</Copyright>
|
||||
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
|
||||
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
|
||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,38 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Photino.Blazor;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
[STAThread]
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
System.IO.Directory.SetCurrentDirectory(AppContext.BaseDirectory);
|
||||
|
||||
var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);
|
||||
|
||||
appBuilder.RootComponents.Add<App>("#app");
|
||||
|
||||
appBuilder.Services.ThingsGatewayComponentsConfigureServices();
|
||||
var app = appBuilder.Build();
|
||||
app.MainWindow.SetTitle("ThingsGateway.Foundation.Demo");
|
||||
app.MainWindow.SetIconFile("wwwroot/favicon.ico");
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
|
||||
{
|
||||
};
|
||||
|
||||
app.Run();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Photino.Blazor" Version="2.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation.Demo.Rcl\ThingsGateway.Foundation.Demo.Rcl.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,26 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||
/// <summary>
|
||||
/// 调试UI
|
||||
/// </summary>
|
||||
public abstract class DriverDebugUIBase : ComponentBase, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志缓存
|
||||
/// </summary>
|
||||
public ConcurrentLinkedList<(LogLevel level, string message)> Messages = new();
|
||||
|
||||
private PeriodicTimer _periodicTimer = new(TimeSpan.FromSeconds(1));
|
||||
|
||||
/// <inheritdoc/>
|
||||
~DriverDebugUIBase()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 变量地址
|
||||
/// </summary>
|
||||
public virtual string Address { get; set; } = "40001";
|
||||
|
||||
/// <summary>
|
||||
/// 长度
|
||||
/// </summary>
|
||||
public virtual int Length { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 默认读写设备
|
||||
/// </summary>
|
||||
public virtual IReadWrite Plc { get; set; }
|
||||
/// <summary>
|
||||
/// 写入值
|
||||
/// </summary>
|
||||
public virtual string WriteValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据类型
|
||||
/// </summary>
|
||||
protected virtual DataTypeEnum DataTypeEnum { get; set; } = DataTypeEnum.Int16;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
[Inject]
|
||||
public InitTimezone InitTimezone { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_periodicTimer?.Dispose();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void LogOut(ThingsGateway.Foundation.LogLevel logLevel, object source, string message, Exception exception)
|
||||
{
|
||||
Messages.Add(((LogLevel)logLevel,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {message} {exception}"));
|
||||
if (Messages.Count > 2500)
|
||||
{
|
||||
Messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task ReadAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = await Plc.ReadAsync(Address, Length, DataTypeEnum);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Messages.Add((LogLevel.Information,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 对应类型值:{Environment.NewLine}{data.Content.ToJsonString(true)} "));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((LogLevel.Warning,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {data.Message}"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((LogLevel.Error,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 错误:{ex.Message}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task WriteAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = await Plc.WriteAsync(Address, WriteValue, Length, DataTypeEnum);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Messages.Add((LogLevel.Information,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {data.Message}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Add((LogLevel.Warning,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {data.Message}"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((LogLevel.Error,
|
||||
$"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入前失败:{ex.Message}"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_ = RunTimerAsync();
|
||||
base.OnInitialized();
|
||||
}
|
||||
private async Task RunTimerAsync()
|
||||
{
|
||||
while (await _periodicTimer.WaitForNextTickAsync())
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@using BlazorComponent;
|
||||
@using Microsoft.AspNetCore.Components.Web;
|
||||
@using Microsoft.JSInterop;
|
||||
@using ThingsGateway.Foundation;
|
||||
@using Masa.Blazor;
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@inherits DriverDebugUIBase
|
||||
|
||||
<MCard Elevation="1" Rounded="false" Class=" pa-2" Style="width:100%">
|
||||
<MRow Class="my-1" Justify="JustifyTypes.Start" Align="AlignTypes.Start" NoGutters>
|
||||
|
||||
<MCol Md="5">
|
||||
<MTabs @bind-Value="tab" Class="ma-2">
|
||||
<MTab Value=1> 读写测试 </MTab>
|
||||
<MTab Value=2> 特殊功能 </MTab>
|
||||
<MTab Value=3> 代码示例 </MTab>
|
||||
</MTabs>
|
||||
|
||||
<MTabsItems Value="tab">
|
||||
<MTabItem Value="1">
|
||||
@if (tab == 1)
|
||||
{
|
||||
@if (ReadWriteContent == null)
|
||||
{
|
||||
|
||||
<div class="my-1 py-1">
|
||||
<MTooltip Bottom Context="tip">
|
||||
<ActivatorContent>
|
||||
<MTextarea Class="mx-1 my-1" Label="变量地址" @attributes="@tip.Attrs" Dense Outlined HideDetails="@("auto")" @bind-Value=@Address />
|
||||
</ActivatorContent>
|
||||
<ChildContent>
|
||||
<span style="white-space: pre-wrap;">@Plc?.GetAddressDescription()</span>
|
||||
</ChildContent>
|
||||
</MTooltip>
|
||||
<MRow Class="my-1" Justify="JustifyTypes.Start" Align="AlignTypes.Start" NoGutters>
|
||||
<MTextField Class="mx-1 my-1" Style="max-width:200px" Label="读取长度" Dense Outlined HideDetails="@("auto")" @bind-Value=@Length />
|
||||
<MSelect Class="mx-1 my-1" Style="max-width:200px" @bind-Value="DataTypeEnum" Outlined Label="数据类型"
|
||||
Items=@(typeof(DataTypeEnum).GetEnumListWithOutSugar())
|
||||
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
|
||||
ItemText=@((u) =>u.Description)
|
||||
ItemValue=@(u =>(DataTypeEnum)u.Value)
|
||||
HideDetails=@("auto") Height="30"
|
||||
Dense>
|
||||
</MSelect>
|
||||
</MRow>
|
||||
|
||||
<MButton Class="mx-1 my-1" Color="primary" OnClick="ReadAsync">
|
||||
读取
|
||||
</MButton>
|
||||
<MTextarea Class="mx-1 mt-3 my-1" Label="值" Dense Outlined HideDetails="@("auto")" @bind-Value=@WriteValue />
|
||||
<MButton Class="mx-1 my-1" Color="primary" OnClick="WriteAsync">
|
||||
写入
|
||||
</MButton>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ReadWriteContent
|
||||
}
|
||||
}
|
||||
</MTabItem>
|
||||
|
||||
<MTabItem Value="2">
|
||||
@if (tab == 2)
|
||||
{
|
||||
@if (ShowDefaultOtherContent)
|
||||
{
|
||||
<MSubheader>
|
||||
连读打包
|
||||
</MSubheader>
|
||||
<MContainer>
|
||||
|
||||
@foreach (var item in DeviceVariableRunTimes)
|
||||
{
|
||||
<MRow Dense Align="AlignTypes.Center">
|
||||
<MTextField Class="ma-1" Outlined Style="min-width:100px" Label=@(item.DescriptionWithOutSugar(x => x.VariableAddress)) Dense HideDetails="@("auto")" @bind-Value=@item.VariableAddress></MTextField>
|
||||
<MSelect Class="mx-1 my-1" Style="max-width:120px" @bind-Value="item.DataTypeEnum" Outlined Label=@(item.DescriptionWithOutSugar(x => x.DataTypeEnum))
|
||||
Items=@(typeof(DataTypeEnum).GetEnumListWithOutSugar())
|
||||
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
|
||||
ItemText=@((u) =>u.Description)
|
||||
ItemValue=@(u =>(DataTypeEnum)u.Value)
|
||||
HideDetails=@("auto") Height="30"
|
||||
Dense>
|
||||
</MSelect>
|
||||
|
||||
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=@(item.DescriptionWithOutSugar(x => x.IntervalTime)) Dense HideDetails="@("auto")" @bind-Value=@item.IntervalTime></MTextField>
|
||||
|
||||
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label=实时值 Readonly ClearIcon="" Dense HideDetails="@("auto")" Value=item.Value?.ToJsonString()></MTextField>
|
||||
|
||||
</MRow>
|
||||
}
|
||||
<MRow Dense>
|
||||
<MTextField Class="ma-1" Outlined Style="max-width:100px" Label="打包长度" Dense HideDetails="@("auto")" @bind-Value=@MaxPack></MTextField>
|
||||
<MButton Class="ma-1" Color="primary" OnClick="MulReadAsync">
|
||||
读取
|
||||
</MButton>
|
||||
</MRow>
|
||||
</MContainer>
|
||||
|
||||
}
|
||||
|
||||
@if (OtherContent != null)
|
||||
{
|
||||
<MSheet Style="height:100%;overflow-y:auto">
|
||||
@OtherContent
|
||||
</MSheet>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
</MTabItem>
|
||||
|
||||
|
||||
<MTabItem Value="3">
|
||||
@if (tab == 3)
|
||||
{
|
||||
@if (CodeContent != null)
|
||||
@CodeContent
|
||||
else
|
||||
{
|
||||
|
||||
<MRow Align="AlignTypes.Center">
|
||||
<MContainer>
|
||||
|
||||
<MItemGroup @bind-Value="_selected" Class="shrink mr-6" Mandatory>
|
||||
@{
|
||||
|
||||
int index = 0;
|
||||
|
||||
}
|
||||
<MRow>
|
||||
|
||||
@foreach (var item in Sections)
|
||||
{
|
||||
<MItem Value="@(index++)">
|
||||
<div>
|
||||
<MButton IsActive="@context.Active" Icon OnClick="@context.Toggle">
|
||||
<MIcon>mdi-record</MIcon>
|
||||
</MButton>
|
||||
</div>
|
||||
</MItem>
|
||||
}
|
||||
</MRow>
|
||||
</MItemGroup>
|
||||
</MContainer>
|
||||
|
||||
<MCol>
|
||||
<MWindow Value="_selected" Vertical Class="elevation-1 grey lighten-5 rounded-b" Style=@($"height:450px;overflow:auto")>
|
||||
@{
|
||||
int index = 0;
|
||||
}
|
||||
@foreach (var item in Sections)
|
||||
{
|
||||
<MWindowItem Value="@(index++)">
|
||||
<AppCode RoundedTop0 Code="@item.Code" Language="@item.Language" />
|
||||
</MWindowItem>
|
||||
}
|
||||
</MWindow>
|
||||
</MCol>
|
||||
</MRow>
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</MTabItem>
|
||||
</MTabsItems>
|
||||
|
||||
</MCol>
|
||||
|
||||
<MCol Md="7">
|
||||
<MCard Style="overflow-y:auto;width:100%" Elevation="0" Flat Class="ml-4">
|
||||
<ConsoleTxt Messages="Messages" Height=500></ConsoleTxt>
|
||||
</MCard>
|
||||
</MCol>
|
||||
|
||||
</MRow>
|
||||
|
||||
</MCard>
|
||||
|
||||
|
||||
@code {
|
||||
StringNumber tab;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using BlazorComponent;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public partial class DriverDebugUIPage : DriverDebugUIBase
|
||||
{
|
||||
/// <summary>
|
||||
/// DeviceVariableRunTimes
|
||||
/// </summary>
|
||||
public List<DeviceVariableRunTime> DeviceVariableRunTimes;
|
||||
/// <summary>
|
||||
/// MaxPack
|
||||
/// </summary>
|
||||
public int MaxPack = 100;
|
||||
/// <summary>
|
||||
/// MulReadAsync
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task MulReadAsync()
|
||||
{
|
||||
var deviceVariableSourceReads = Plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(DeviceVariableRunTimes, MaxPack);
|
||||
foreach (var item in deviceVariableSourceReads)
|
||||
{
|
||||
var result = await Plc.ReadAsync(item.VariableAddress, item.Length);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
item.DeviceVariableRunTimes.PraseStructContent(Plc, result.Content);
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Content.ToHexString(' ')));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + ex.Message));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + result.Message));
|
||||
}
|
||||
}
|
||||
|
||||
private StringNumber _selected = 0;
|
||||
/// <summary>
|
||||
/// Sections
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<(string Code, string Language)> Sections { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// ShowDefaultOtherContent
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowDefaultOtherContent { get; set; } = true;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
DeviceVariableRunTimes = new()
|
||||
{
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40001",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40011",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40031",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40101",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
};
|
||||
Sections.Add((
|
||||
"""
|
||||
/// <inheritdoc/>
|
||||
public class DeviceVariableSourceRead : IDeviceVariableSourceRead<DeviceVariableRunTime>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public TimerTick TimerTick { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public string VariableAddress { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public int Length { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public List<DeviceVariableRunTime> DeviceVariableRunTimes { get; set; } = new List<DeviceVariableRunTime>();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public class DeviceVariableRunTime : IDeviceVariableRunTime
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[Description("读取间隔")]
|
||||
public int IntervalTime { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("变量地址")]
|
||||
public string VariableAddress { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public int Index { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public IThingsGatewayBitConverter ThingsGatewayBitConverter { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("数据类型")]
|
||||
public DataTypeEnum DataTypeEnum { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("实时值")]
|
||||
public object Value { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public OperResult SetValue(object value)
|
||||
{
|
||||
Value = value;
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
}
|
||||
public List<DeviceVariableRunTime> DeviceVariableRunTimes;
|
||||
|
||||
private static async Task ModbusClientAsync(IReadWrite plc)
|
||||
{
|
||||
DeviceVariableRunTimes = new()
|
||||
{
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40001",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40011",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40031",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
new DeviceVariableRunTime()
|
||||
{
|
||||
DataTypeEnum=DataTypeEnum.Int16,
|
||||
VariableAddress="40101",
|
||||
IntervalTime=1000,
|
||||
},
|
||||
};
|
||||
|
||||
#region 连读
|
||||
var deviceVariableSourceReads = Plc.LoadSourceRead<DeviceVariableSourceRead, DeviceVariableRunTime>(DeviceVariableRunTimes, MaxPack);
|
||||
foreach (var item in deviceVariableSourceReads)
|
||||
{
|
||||
var result = await Plc.ReadAsync(item.VariableAddress, item.Length);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
item.DeviceVariableRunTimes.PraseStructContent(result.Content);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
""", "csharp"));
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义模板
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ReadWriteContent { get; set; }
|
||||
/// <summary>
|
||||
/// 自定义模板
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment OtherContent { get; set; }
|
||||
/// <summary>
|
||||
/// 自定义模板
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment CodeContent { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
~DriverDebugUIPage()
|
||||
{
|
||||
this.SafeDispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public override IReadWrite Plc { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Dispose()
|
||||
{
|
||||
Plc?.SafeDispose();
|
||||
base.Dispose();
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using BlazorComponent;
|
||||
@using Microsoft.AspNetCore.Components.Web;
|
||||
@using System.IO.Ports;
|
||||
@using Masa.Blazor
|
||||
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
|
||||
<div class="mb-4">通道配置</div>
|
||||
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
|
||||
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.PortName)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.PortName />
|
||||
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.BaudRate)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.BaudRate />
|
||||
<MTextField Style="max-width:100px" Class="ma-1" Outlined Label=@(serialProperty.DescriptionWithOutSugar(x => x.DataBits)) Dense HideDetails="@("auto")" @bind-Value=@serialProperty.DataBits />
|
||||
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="serialProperty.Parity" Label="@(serialProperty.DescriptionWithOutSugar(x => x.Parity))"
|
||||
Items=@(typeof(Parity).GetEnumListWithOutSugar())
|
||||
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
|
||||
ItemText=@((u) =>u.Description)
|
||||
ItemValue=@(u =>(Parity)u.Value)
|
||||
HideDetails=@("auto") Height="30"
|
||||
Dense>
|
||||
</MSelect>
|
||||
<MSelect Class="ma-1 " Style="max-width:200px" Outlined @bind-Value="serialProperty.StopBits" Label="@(serialProperty.DescriptionWithOutSugar(x => x.StopBits))"
|
||||
Items=@(typeof(StopBits).GetEnumListWithOutSugar())
|
||||
MenuProps="@(props => { props.Auto = true; props.OffsetY = true; })"
|
||||
ItemText=@((u) =>u.Description)
|
||||
ItemValue=@(u =>(StopBits)u.Value)
|
||||
HideDetails=@("auto") Height="30"
|
||||
Dense>
|
||||
</MSelect>
|
||||
<MButton Class="ma-1" OnClick=@ConnectAsync Color="primary">
|
||||
连接
|
||||
</MButton>
|
||||
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
|
||||
断开
|
||||
</MButton>
|
||||
</MRow>
|
||||
</MCard>
|
||||
@@ -1,106 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public partial class SerialSessionPage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
private TouchSocketConfig config;
|
||||
|
||||
private readonly SerialProperty serialProperty = new();
|
||||
|
||||
private SerialSession SerialSession { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SerialSession GetSerialSession()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetSerialProperty(serialProperty);
|
||||
//载入配置
|
||||
SerialSession.Setup(config);
|
||||
return SerialSession;
|
||||
}
|
||||
private async Task ConnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
SerialSession.Close();
|
||||
await GetSerialSession().ConnectAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
private void DisConnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
SerialSession.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
SerialSession.Setup(config);
|
||||
}
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
|
||||
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
SerialSession.SafeDispose();
|
||||
}
|
||||
internal void StateHasChangedAsync()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using BlazorComponent;
|
||||
@using Microsoft.AspNetCore.Components.Web;
|
||||
@using System.IO.Ports;
|
||||
@using System.Collections.Concurrent;
|
||||
@using ThingsGateway.Foundation;
|
||||
@using Masa.Blazor
|
||||
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
|
||||
<div class="mb-4">通道配置</div>
|
||||
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
|
||||
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@IP />
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@Port />
|
||||
|
||||
<MButton Class="ma-1" OnClick=@ConnectAsync Color="primary">
|
||||
连接
|
||||
</MButton>
|
||||
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
|
||||
断开
|
||||
</MButton>
|
||||
</MRow>
|
||||
</MCard>
|
||||
@@ -1,116 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public partial class TcpClientPage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
private TouchSocketConfig config;
|
||||
/// <summary>
|
||||
/// IP
|
||||
/// </summary>
|
||||
private string IP = "127.0.0.1";
|
||||
/// <summary>
|
||||
/// Port
|
||||
/// </summary>
|
||||
public int Port { get; set; } = 502;
|
||||
|
||||
private TcpClient TcpClient { get; set; } = new();
|
||||
|
||||
private async Task ConnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpClient.Close();
|
||||
await GetTcpClient().ConnectAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
private void DisConnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpClient.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TcpClient GetTcpClient()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
|
||||
//载入配置
|
||||
TcpClient.Setup(config);
|
||||
return TcpClient;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
|
||||
TcpClient.Setup(config);
|
||||
}
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
|
||||
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
TcpClient.SafeDispose();
|
||||
}
|
||||
|
||||
internal void StateHasChangedAsync()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using BlazorComponent;
|
||||
@using Microsoft.AspNetCore.Components.Web;
|
||||
@using System.IO.Ports;
|
||||
@using System.Collections.Concurrent;
|
||||
@using ThingsGateway.Foundation;
|
||||
@using Masa.Blazor
|
||||
|
||||
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
|
||||
<div class="mb-4">通道配置</div>
|
||||
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
|
||||
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@ip />
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@port />
|
||||
|
||||
<MButton Class="ma-1" OnClick=@Connect Color="primary">
|
||||
连接
|
||||
</MButton>
|
||||
<MButton Class="ma-1" OnClick=@DisConnect Color="red">
|
||||
断开
|
||||
</MButton>
|
||||
|
||||
|
||||
|
||||
</MRow>
|
||||
</MCard>
|
||||
@@ -1,108 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public partial class TcpServerPage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
private TouchSocketConfig config;
|
||||
|
||||
private string ip = "127.0.0.1";
|
||||
|
||||
private int port = 502;
|
||||
|
||||
private TcpService TcpServer { get; set; } = new();
|
||||
|
||||
private void Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpServer.Stop();
|
||||
GetTcpServer().Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
private void DisConnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpServer.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TcpService GetTcpServer()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
|
||||
//载入配置
|
||||
TcpServer.Setup(config);
|
||||
return TcpServer;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetListenIPHosts(new IPHost[] { new IPHost(ip + ":" + port) });
|
||||
TcpServer.Setup(config);
|
||||
}
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
|
||||
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
TcpServer.SafeDispose();
|
||||
}
|
||||
internal void StateHasChangedAsync()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using BlazorComponent;
|
||||
@using Microsoft.AspNetCore.Components.Web;
|
||||
@using System.IO.Ports;
|
||||
@using System.Collections.Concurrent;
|
||||
@using ThingsGateway.Foundation;
|
||||
@using Masa.Blazor
|
||||
|
||||
<MCard Elevation="1" Rounded="false" Class="pa-2" Style="width:100%">
|
||||
<div class="mb-4">通道配置</div>
|
||||
<MRow Justify="JustifyTypes.Start" Align="AlignTypes.Center">
|
||||
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="IP地址" Dense Outlined HideDetails="@("auto")" @bind-Value=@IP />
|
||||
<MTextField Class="ma-1" Style="max-width:100px" Label="端口" Dense Outlined HideDetails="@("auto")" @bind-Value=@Port />
|
||||
|
||||
<MButton Class="ma-1" OnClick=Connect Color="primary">
|
||||
连接
|
||||
</MButton>
|
||||
<MButton Class="ma-1" OnClick=DisConnect Color="red">
|
||||
断开
|
||||
</MButton>
|
||||
|
||||
|
||||
</MRow>
|
||||
</MCard>
|
||||
@@ -1,113 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public partial class UdpSessionPage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志输出
|
||||
/// </summary>
|
||||
public Action<LogLevel, object, string, Exception> LogAction;
|
||||
|
||||
private TouchSocketConfig config;
|
||||
/// <summary>
|
||||
/// IP
|
||||
/// </summary>
|
||||
public string IP = "127.0.0.1";
|
||||
/// <summary>
|
||||
/// Port
|
||||
/// </summary>
|
||||
public int Port = 502;
|
||||
|
||||
private UdpSession UdpSession { get; set; } = new();
|
||||
|
||||
private void Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
UdpSession.Stop();
|
||||
GetUdpSession().Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
private void DisConnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
UdpSession.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
LogAction?.Invoke(LogLevel.Error, null, null, ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public UdpSession GetUdpSession()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
|
||||
config.SetBindIPHost(new IPHost(0));
|
||||
//载入配置
|
||||
UdpSession.Setup(config);
|
||||
return UdpSession;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
config ??= new TouchSocketConfig();
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
var LogMessage = new LoggerGroup() { LogLevel = LogLevel.Trace };
|
||||
LogMessage.AddLogger(new EasyLogger(LogOut) { LogLevel = LogLevel.Trace });
|
||||
config.ConfigureContainer(a => a.RegisterSingleton<ILog>(LogMessage));
|
||||
config.SetRemoteIPHost(new IPHost(IP + ":" + Port));
|
||||
config.SetBindIPHost(new IPHost(0));
|
||||
UdpSession.Setup(config);
|
||||
}
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
private void LogOut(LogLevel logLevel, object source, string message, Exception exception) => LogAction?.Invoke(logLevel, source, message, exception);
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
UdpSession.SafeDispose();
|
||||
}
|
||||
internal void StateHasChangedAsync()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class DeviceVariableRunTime : IDeviceVariableRunTime
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[Description("读取间隔")]
|
||||
public int IntervalTime { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("变量地址")]
|
||||
public string VariableAddress { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public int Index { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public IThingsGatewayBitConverter ThingsGatewayBitConverter { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("数据类型")]
|
||||
public DataTypeEnum DataTypeEnum { get; set; }
|
||||
/// <inheritdoc/>
|
||||
[Description("实时值")]
|
||||
public object Value { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public OperResult SetValue(object value, DateTime dateTime = default, bool isOnline = true)
|
||||
{
|
||||
Value = value;
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class DeviceVariableSourceRead : IDeviceVariableSourceRead<IDeviceVariableRunTime>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public TimerTick TimerTick { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public string VariableAddress { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public int Length { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public List<IDeviceVariableRunTime> DeviceVariableRunTimes { get; set; } = new List<IDeviceVariableRunTime>();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
global using System;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
|
||||
global using ThingsGateway.Components;
|
||||
global using ThingsGateway.Foundation.Serial;
|
||||
global using ThingsGateway.Foundation.Sockets;
|
||||
@@ -1,36 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@page "/"
|
||||
@layout BaseLayout
|
||||
@inject NavigationManager NavigationManager
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
@code {
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
NavigationManager.NavigateTo("index");
|
||||
}
|
||||
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@page "/index"
|
||||
|
||||
<div class="ml-2">
|
||||
<div class="my-6 ">
|
||||
<MLabel Class="text-h3" Color="primary">ThingsGateway</MLabel>
|
||||
</div>
|
||||
<div>
|
||||
<strong class="text--lighten-1 text-h5 my-1">文档</strong>
|
||||
</div>
|
||||
<div class="my-2 ml-4">
|
||||
<PCopyableText>
|
||||
https://diego2098.gitee.io/thingsgateway-docs/
|
||||
</PCopyableText>
|
||||
</div>
|
||||
<div>
|
||||
<strong class="text--lighten-1 text-h5 my-1">协议</strong>
|
||||
</div>
|
||||
<div class="my-2 ml-4">
|
||||
<PCopyableText Text="https://gitee.com/diego2098/ThingsGateway/blob/master/LICENSE.zh">
|
||||
Apache-2.0开源协议
|
||||
</PCopyableText>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong class="text--lighten-1 text-h5 my-1">赞助</strong>
|
||||
</div>
|
||||
<div class="my-2 ml-4">
|
||||
<PCopyableText Text="https://diego2098.gitee.io/thingsgateway-docs/docs/donate">
|
||||
ThingsGateway赞助途径
|
||||
</PCopyableText>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong class="text--lighten-1 text-h5 my-1">社区</strong>
|
||||
</div>
|
||||
<div class="my-2 ml-4">
|
||||
<PCopyableText Text="605534569">
|
||||
QQ群:605534569
|
||||
</PCopyableText>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<CascadingValue Value="IsMobile" Name="IsMobile">
|
||||
<MApp>
|
||||
<MErrorHandler>
|
||||
@Body
|
||||
</MErrorHandler>
|
||||
</MApp>
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
public bool IsMobile { get; set; }
|
||||
[Inject]
|
||||
public MasaBlazor MasaBlazor { get; set; }
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
MasaBlazor.BreakpointChanged += BreakpointOnOnUpdate;
|
||||
}
|
||||
|
||||
private void BreakpointOnOnUpdate(object sender, BreakpointChangedEventArgs e)
|
||||
{
|
||||
IsMobile = MasaBlazor.Breakpoint.Mobile;
|
||||
if (e.MobileChanged)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@namespace ThingsGateway.Foundation.Demo
|
||||
@using System.Text;
|
||||
@inherits LayoutComponentBase
|
||||
@layout BaseLayout
|
||||
|
||||
<PPageTabsProvider>
|
||||
|
||||
<CascadingValue Value="@this" IsFixed>
|
||||
<CascadingValue Value="@Changed" Name="Changed">
|
||||
|
||||
<MNavigationDrawer Color="barcolor" @bind-Value="_drawerOpen" App Width="200">
|
||||
<Logo CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_TITLE=@CONFIG_TITLE HeightInt=@(IsMobile?BlazorResourceConst.AppBarHeight:BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight) />
|
||||
<AppList ClassString="overflow-y-auto" Routable
|
||||
StyleString=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight}px);")
|
||||
Items="Navs" />
|
||||
</MNavigationDrawer>
|
||||
|
||||
<MAppBar Color="barcolor" Style=@($"{(!(IsMobile||_drawerOpen!=true)? "left:200px;":"")}") Elevation="1" App Flat ClippedRight Dense ElevateOnScroll
|
||||
MaxHeight="@(BlazorResourceConst.AppBarHeight)" Height="@(BlazorResourceConst.AppBarHeight)">
|
||||
<MButton Class="mr-0" Icon Small=IsMobile OnClick=@(() => _drawerOpen = !_drawerOpen)>
|
||||
<MIcon>mdi-menu</MIcon>
|
||||
</MButton>
|
||||
|
||||
</MAppBar>
|
||||
|
||||
<MMain Style=@($"{(!(IsMobile||_drawerOpen!=true)? "padding-left:200px;":"")}")>
|
||||
<div class="full-width">
|
||||
<PageTabs @ref="_pageTabs" PageTabItems="pageTabItems" />
|
||||
</div>
|
||||
<MDivider Center></MDivider>
|
||||
<MCard Flat Class="overflow-y-auto overflow-x-hidden ma-auto pa-0 rounded-0" Style=@($"height: calc(100vh - {BlazorResourceConst.AppBarHeight+BlazorResourceConst.PageTabsHeight+BlazorResourceConst.FooterHeight}px);")>
|
||||
<PPageContainer PageTabs="@_pageTabs?.PPageTabs">
|
||||
@Body
|
||||
</PPageContainer>
|
||||
</MCard>
|
||||
<MSheet Class="d-flex justify-center align-center rounded-0" Style=@($"height: {BlazorResourceConst.FooterHeight}px;")>
|
||||
<Foter CONFIG_COPYRIGHT=@CONFIG_COPYRIGHT CONFIG_COPYRIGHT_URL=@CONFIG_COPYRIGHT_URL CONFIG_TITLE=@CONFIG_TITLE></Foter>
|
||||
</MSheet>
|
||||
</MMain>
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
|
||||
</PPageTabsProvider>
|
||||
@code {
|
||||
bool Changed { get; set; }
|
||||
private bool? _drawerOpen = true;
|
||||
|
||||
private PageTabs _pageTabs;
|
||||
|
||||
/// <summary>
|
||||
/// IsMobile
|
||||
/// </summary>
|
||||
[CascadingParameter(Name = "IsMobile")]
|
||||
public bool IsMobile { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@code{
|
||||
private string CONFIG_COPYRIGHT = "Diego";
|
||||
private string CONFIG_COPYRIGHT_URL = "https://gitee.com/diego2098/ThingsGateway";
|
||||
private string CONFIG_TITLE = "ThingsGateway";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>Ϊȫ<CEAA>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>
|
||||
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4>룩<EFBFBD><EBA3A9><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><DFB1><EFBFBD>Diego<67><6F><EFBFBD><EFBFBD>
|
||||
// Դ<><D4B4><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>ֿ<EFBFBD><D6BF>Ŀ<EFBFBD>ԴЭ<D4B4>鼰<EFBFBD><E9BCB0><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>
|
||||
// GiteeԴ<65><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://gitee.com/diego2098/ThingsGateway
|
||||
// GithubԴ<62><D4B4><EFBFBD><EFBFBD><EFBFBD>ֿ⣺https://github.com/kimdiego2098/ThingsGateway
|
||||
// ʹ<><CAB9><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQȺ<51><C8BA>605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Demo;
|
||||
|
||||
public partial class MainLayout
|
||||
{
|
||||
|
||||
private List<NavItem> Navs { get; set; } = new();
|
||||
private List<PageTabItem> pageTabItems { get; set; } = new();
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
var dataString =
|
||||
"""
|
||||
[
|
||||
{
|
||||
"Href": "/index",
|
||||
"Title": "<22><>ҳ"
|
||||
},
|
||||
{
|
||||
"Title": "Modbus",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/ModbusRtu",
|
||||
"Title": "ModbusRtu"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusTcp",
|
||||
"Title": "ModbusTcp"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusRtuOverTcp",
|
||||
"Title": "ModbusRtuOverTcp"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusRtuOverUdp",
|
||||
"Title": "ModbusRtuOverUdp"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusUdp",
|
||||
"Title": "ModbusUdp"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusTcpDtu",
|
||||
"Title": "ModbusTcpDtu"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusTcpServer",
|
||||
"Title": "ModbusTcpServer"
|
||||
},
|
||||
{
|
||||
"Href": "/ModbusSerialServer",
|
||||
"Title": "ModbusSerialServer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "Siemens",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/S7_1500",
|
||||
"Title": "S7_1500"
|
||||
},
|
||||
{
|
||||
"Href": "/S7_1200",
|
||||
"Title": "S7_1200"
|
||||
},
|
||||
{
|
||||
"Href": "/S7_200",
|
||||
"Title": "S7_200"
|
||||
},
|
||||
{
|
||||
"Href": "/S7_200SMART",
|
||||
"Title": "S7_200SMART"
|
||||
},
|
||||
{
|
||||
"Href": "/S7_300",
|
||||
"Title": "S7_400"
|
||||
},
|
||||
{
|
||||
"Href": "/S7_400",
|
||||
"Title": "S7_400"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "DLT645",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/DLT645_2007",
|
||||
"Title": "DLT645_2007"
|
||||
},
|
||||
{
|
||||
"Href": "/DLT645_2007OverTcp",
|
||||
"Title": "DLT645_2007OverTcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "OPCDA",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/OPCDAClient",
|
||||
"Title": "OPCDAClient"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "OPCUA",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/OPCUAClient",
|
||||
"Title": "OPCUAClient"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
""";
|
||||
Navs = dataString.FromJsonString<List<NavItem>>();
|
||||
|
||||
#if Pro
|
||||
var dataStringPro =
|
||||
"""
|
||||
[
|
||||
{
|
||||
"Title": "ABCIP",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/ABCIPTCP",
|
||||
"Title": "ABCIPTCP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "Omron",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/OmronFinsTcp",
|
||||
"Title": "OmronFinsTcp"
|
||||
},
|
||||
{
|
||||
"Href": "/OmronFinsUdp",
|
||||
"Title": "OmronFinsUdp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "Secs",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/SecsTcp",
|
||||
"Title": "SecsTcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "TS550",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/TS550",
|
||||
"Title": "TS550"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "Vigor",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/VigorSerial",
|
||||
"Title": "VigorSerial"
|
||||
},
|
||||
{
|
||||
"Href": "/VigorSerialOverTcp",
|
||||
"Title": "VigorSerialOverTcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "GasCustom",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/GasCustomSerial",
|
||||
"Title": "GasCustomSerial"
|
||||
},
|
||||
{
|
||||
"Href": "/GasCustomSerialOverTcp",
|
||||
"Title": "GasCustomSerialOverTcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
||||
""";
|
||||
Navs.AddRange(dataStringPro.FromJsonString<List<NavItem>>());
|
||||
#endif
|
||||
pageTabItems = Navs.PasePageTabItem();
|
||||
base.OnInitialized();
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
|
||||
<DefineConstants>Pro</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(SolutionName)'=='ThingsGateway - Pro'">
|
||||
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor.cs" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.AllenBradleyCip\Page\AllenBradleyCipTcpDebugPage.razor" Link="Pages\ABCIP\AllenBradleyCipTcpDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.AllenBradleyCip\ThingsGateway.Foundation.Adapter.AllenBradleyCip.csproj" />
|
||||
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsTcpDebugPage.razor.cs" Link="Pages\OmronFins\OmronFinsTcpDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsUdpDebugPage.razor.cs" Link="Pages\OmronFins\OmronFinsUdpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsTcpDebugPage.razor" Link="Pages\OmronFins\OmronFinsTcpDebugPage.razor" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Omron\Page\OmronFinsUdpDebugPage.razor" Link="Pages\OmronFins\OmronFinsUdpDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Omron\ThingsGateway.Foundation.Adapter.Omron.csproj" />
|
||||
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Secs\Page\SecsHsmsTcpDebugPage.razor.cs" Link="Pages\Secs\SecsHsmsTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Secs\Page\SecsHsmsTcpDebugPage.razor" Link="Pages\Secs\SecsHsmsTcpDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Secs\ThingsGateway.Foundation.Adapter.Secs.csproj" />
|
||||
|
||||
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.TS550\Page\TS550DebugPage.razor.cs" Link="Pages\TS550\TS550DebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.TS550\Page\TS550DebugPage.razor" Link="Pages\TS550\TS550DebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.TS550\ThingsGateway.Foundation.Adapter.TS550.csproj" />
|
||||
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialDebugPage.razor.cs" Link="Pages\Vigor\VigorSerialDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialOverTcpDebugPage.razor.cs" Link="Pages\Vigor\VigorSerialOverTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialDebugPage.razor" Link="Pages\Vigor\VigorSerialDebugPage.razor" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Vigor\Page\VigorSerialOverTcpDebugPage.razor" Link="Pages\Vigor\VigorSerialOverTcpDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Vigor\ThingsGateway.Foundation.Adapter.Vigor.csproj" />
|
||||
|
||||
|
||||
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialDebugPage.razor" />
|
||||
<Content Include="..\..\PluginProAF2021\ThingsGateway.Plugin.HZW_QTJC_01\Page\HZW_QTJC_01SerialOverTcpDebugPage.razor" Link="Pages\HZW_QTJC_01\HZW_QTJC_01SerialOverTcpDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\PluginProAF2021\ThingsGateway.Foundation.Adapter.HZW_QTJC_01\ThingsGateway.Foundation.Adapter.HZW_QTJC_01.csproj" />
|
||||
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007DebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007DebugPage.razor" Link="Pages\DLT645\DLT645_2007DebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor.cs" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.DLT645\Page\DLT645_2007OverTcpDebugPage.razor" Link="Pages\DLT645\DLT645_2007OverTcpDebugPage.razor" />
|
||||
|
||||
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuDebugPage.razor" Link="Pages\Modbus\ModbusRtuDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverTcpDebugPage.razor" Link="Pages\Modbus\ModbusRtuOverTcpDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverUdpDebugPage.razor.cs" Link="Pages\Modbus\ModbusRtuOverUdpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusRtuOverUdpDebugPage.razor" Link="Pages\Modbus\ModbusRtuOverUdpDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusSerialServerDebugPage.razor.cs" Link="Pages\Modbus\ModbusSerialServerDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusSerialServerDebugPage.razor" Link="Pages\Modbus\ModbusSerialServerDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDebugPage.razor" Link="Pages\Modbus\ModbusTcpDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDtuDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpDtuDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpDtuDebugPage.razor" Link="Pages\Modbus\ModbusTcpDtuDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpServerDebugPage.razor.cs" Link="Pages\Modbus\ModbusTcpServerDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusTcpServerDebugPage.razor" Link="Pages\Modbus\ModbusTcpServerDebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusUdpDebugPage.razor.cs" Link="Pages\Modbus\ModbusUdpDebugPage.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Modbus\Page\ModbusUdpDebugPage.razor" Link="Pages\Modbus\ModbusUdpDebugPage.razor" />
|
||||
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientDebugPage.razor.cs" Link="Pages\OPCDA\OPCDAClientDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientPage.razor.cs" Link="Pages\OPCDA\OPCDAClientPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAImportVariable.razor.cs" Link="Pages\OPCDA\OPCDAImportVariable.razor.cs" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientDebugPage.razor" Link="Pages\OPCDA\OPCDAClientDebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAClientPage.razor" Link="Pages\OPCDA\OPCDAClientPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCDA\Page\OPCDAImportVariable.razor" Link="Pages\OPCDA\OPCDAImportVariable.razor" />
|
||||
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientDebugPage.razor" Link="Pages\OPCUA\OPCUAClientDebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientPage.razor" Link="Pages\OPCUA\OPCUAClientPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAImportVariable.razor" Link="Pages\OPCUA\OPCUAImportVariable.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientDebugPage.razor.cs" Link="Pages\OPCUA\OPCUAClientDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAClientPage.razor.cs" Link="Pages\OPCUA\OPCUAClientPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.OPCUA\Page\OPCUAImportVariable.razor.cs" Link="Pages\OPCUA\OPCUAImportVariable.razor.cs" />
|
||||
|
||||
|
||||
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1200DebugPage.razor" Link="Pages\Siemens\S7_1200DebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1500DebugPage.razor" Link="Pages\Siemens\S7_1500DebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200DebugPage.razor" Link="Pages\Siemens\S7_200DebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200SMARTDebugPage.razor" Link="Pages\Siemens\S7_200SMARTDebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_300DebugPage.razor" Link="Pages\Siemens\S7_300DebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_400DebugPage.razor" Link="Pages\Siemens\S7_400DebugPage.razor" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1200DebugPage.razor.cs" Link="Pages\Siemens\S7_1200DebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_1500DebugPage.razor.cs" Link="Pages\Siemens\S7_1500DebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200DebugPage.razor.cs" Link="Pages\Siemens\S7_200DebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_200SMARTDebugPage.razor.cs" Link="Pages\Siemens\S7_200SMARTDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_300DebugPage.razor.cs" Link="Pages\Siemens\S7_300DebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Siemens\Page\S7_400DebugPage.razor.cs" Link="Pages\Siemens\S7_400DebugPage.razor.cs" />
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.DLT645\ThingsGateway.Foundation.Adapter.DLT645.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Modbus\ThingsGateway.Foundation.Adapter.Modbus.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCDA\ThingsGateway.Foundation.Adapter.OPCDA.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.OPCUA\ThingsGateway.Foundation.Adapter.OPCUA.csproj" />
|
||||
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Adapter.Siemens\ThingsGateway.Foundation.Adapter.Siemens.csproj" />
|
||||
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,29 +0,0 @@
|
||||
@*
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
*@
|
||||
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using BlazorComponent
|
||||
@using Masa.Blazor
|
||||
@using Masa.Blazor.Presets
|
||||
@using ThingsGateway.Foundation;
|
||||
@using ThingsGateway.Components;
|
||||
@using ThingsGateway.Core;
|
||||
@using System.Net.Http.Json
|
||||
@using System.IO;
|
||||
@using System.Text.Json;
|
||||
@using ThingsGateway.Foundation.Serial;
|
||||
@using ThingsGateway.Foundation.Sockets;
|
||||
@@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>ThingsGateway.Foundation.Demo</title>
|
||||
<base href="/" />
|
||||
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link href="_content/Masa.Blazor/css/masa-blazor.min.css" rel="stylesheet" />
|
||||
<link href="_content/ThingsGateway.Components/css/materialdesign/v7.1.96/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="_content/ThingsGateway.Components/css/material/icons.css" rel="stylesheet">
|
||||
<link href="_content/ThingsGateway.Components/css/fontawesome/v6.4.0/css/all.min.css" rel="stylesheet">
|
||||
<link href="_content/ThingsGateway.Components/style/custom.css" rel="stylesheet">
|
||||
<link href="_content/ThingsGateway.Components/prism/prism-material-dark-for-masa.css" rel="stylesheet">
|
||||
<link href="_content/ThingsGateway.Components/prism/prism-line-highlight.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
<span>
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
</span>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
|
||||
<script src="_framework/blazor.webview.js" autostart="true"></script>
|
||||
<script src="_content/ThingsGateway.Components/prism/prism.min.js"></script>
|
||||
<script src="_content/BlazorComponent/js/blazor-component.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,46 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>3.0.0.1</Version>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
<Authors>Diego</Authors>
|
||||
<Product>ThingsGateway</Product>
|
||||
<Copyright>© 2023-present Diego</Copyright>
|
||||
<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSource>true</EmbedUntrackedSource>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<RepositoryType>Gitee</RepositoryType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://diego2098.gitee.io/thingsgateway-docs/</PackageProjectUrl>
|
||||
<PackageTags>ThingsGateway;Diego;dotNET China;Blazor;设备采集;边缘网关</PackageTags>
|
||||
<SignAssembly>True</SignAssembly>
|
||||
<DelaySign>False</DelaySign>
|
||||
<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
|
||||
<PackageOutputPath>../../nupkgs</PackageOutputPath>
|
||||
<AssemblyOriginatorKeyFile>../../../snks/ThingsGateway.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\icon.png">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,56 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
|
||||
/// <summary>
|
||||
/// 控制码
|
||||
/// </summary>
|
||||
public enum ControlCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 读数据
|
||||
/// </summary>
|
||||
Read = 0x11,
|
||||
/// <summary>
|
||||
/// 读后续数据
|
||||
/// </summary>
|
||||
ReadSub = 0x12,
|
||||
/// <summary>
|
||||
/// 读站号
|
||||
/// </summary>
|
||||
ReadStation = 0x13,
|
||||
/// <summary>
|
||||
/// 写数据
|
||||
/// </summary>
|
||||
Write = 0x14,
|
||||
/// <summary>
|
||||
/// 写站号
|
||||
/// </summary>
|
||||
WriteStation = 0x15,
|
||||
/// <summary>
|
||||
/// 广播校时
|
||||
/// </summary>
|
||||
BroadcastTime = 0x08,
|
||||
/// <summary>
|
||||
/// 冻结
|
||||
/// </summary>
|
||||
Freeze = 0x16,
|
||||
/// <summary>
|
||||
/// 更新波特率
|
||||
/// </summary>
|
||||
WriteBaudRate = 0x17,
|
||||
/// <summary>
|
||||
/// 更新密码
|
||||
/// </summary>
|
||||
WritePassword = 0x18,
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,481 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
public class DLT645_2007 : ReadWriteDevicesSerialSessionBase
|
||||
{
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
/// <param name="serialSession"></param>
|
||||
public DLT645_2007(SerialSession serialSession) : base(serialSession)
|
||||
{
|
||||
ThingsGatewayBitConverter = new DLT645_2007BitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加FE FE FE FE的报文头部
|
||||
/// </summary>
|
||||
[Description("前导符报文头")]
|
||||
public bool EnableFEHead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入需操作员代码
|
||||
/// </summary>
|
||||
[Description("操作员代码")]
|
||||
public string OperCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入密码
|
||||
/// </summary>
|
||||
[Description("写入密码")]
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通讯地址BCD码,一般应该是12个字符
|
||||
/// </summary>
|
||||
[Description("通讯地址")]
|
||||
public string Station { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
|
||||
var str = """
|
||||
查看附带文档或者相关资料,下面列举一下常见的数据标识地址
|
||||
|
||||
地址 说明
|
||||
-----------------------------------------
|
||||
02010100 A相电压
|
||||
02020100 A相电流
|
||||
02030000 瞬时总有功功率
|
||||
00000000 (当前)组合有功总电能
|
||||
00010000 (当前)正向有功总电能
|
||||
|
||||
""";
|
||||
return base.GetAddressDescription() + Environment.NewLine + str;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
var dataHandleAdapter = new DLT645_2007DataHandleAdapter
|
||||
{
|
||||
EnableFEHead = EnableFEHead
|
||||
};
|
||||
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, string value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
Password ??= string.Empty;
|
||||
OperCode ??= string.Empty;
|
||||
if (Password.Length < 8)
|
||||
Password = Password.PadLeft(8, '0');
|
||||
if (OperCode.Length < 8)
|
||||
OperCode = OperCode.PadLeft(8, '0');
|
||||
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
|
||||
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, string value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
Password ??= string.Empty;
|
||||
OperCode ??= string.Empty;
|
||||
if (Password.Length < 8)
|
||||
Password = Password.PadLeft(8, '0');
|
||||
if (OperCode.Length < 8)
|
||||
OperCode = OperCode.PadLeft(8, '0');
|
||||
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
|
||||
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, uint value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, double value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, float value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, long value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, ulong value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, ushort value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, short value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, int value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
|
||||
|
||||
#region 其他方法
|
||||
|
||||
/// <summary>
|
||||
/// 广播校时
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public OperResult BroadcastTime(DateTime dateTime, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
string str = $"{dateTime.Second:D2}{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}{dateTime.Year % 100:D2}";
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.BroadcastTime, str.ByHexStringToBytes().ToArray(), "999999999999".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
SerialSession.Send(commandResult.Content);
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 冻结
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> FreezeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
string str = $"{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}";
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.Freeze, str.ByHexStringToBytes().ToArray(), Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 读取通信地址
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult<string>> ReadDeviceStationAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.ReadStation, null, "AAAAAAAAAAAA".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
var buffer = result1.Content.SelectMiddle(0, 6).BytesAdd(-0x33);
|
||||
return OperResult.CreateSuccessResult(buffer.Reverse().ToArray().ToHexString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<string>(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<string>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 修改波特率
|
||||
/// </summary>
|
||||
/// <param name="baudRate"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WriteBaudRateAsync(int baudRate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
byte baudRateByte;
|
||||
switch (baudRate)
|
||||
{
|
||||
case 600: baudRateByte = 0x02; break;
|
||||
case 1200: baudRateByte = 0x04; break;
|
||||
case 2400: baudRateByte = 0x08; break;
|
||||
case 4800: baudRateByte = 0x10; break;
|
||||
case 9600: baudRateByte = 0x20; break;
|
||||
case 19200: baudRateByte = 0x40; break;
|
||||
default: return new OperResult<string>($"不支持此波特率:{baudRate}");
|
||||
}
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteBaudRate, new byte[] { baudRateByte }, Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新通信地址
|
||||
/// </summary>
|
||||
/// <param name="station"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WriteDeviceStationAsync(string station, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteStation, station.ByHexStringToBytes().Reverse().ToArray(), "AAAAAAAAAAAA".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改密码
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="oldPassword"></param>
|
||||
/// <param name="newPassword"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WritePasswordAsync(byte level, string oldPassword, string newPassword, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
string str = $"04000C{(level + 1):D2}";
|
||||
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword,
|
||||
str.ByHexStringToBytes().Reverse().ToArray()
|
||||
.SpliceArray(oldPassword.ByHexStringToBytes().Reverse().ToArray())
|
||||
.SpliceArray(newPassword.ByHexStringToBytes().Reverse().ToArray())
|
||||
, Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.String;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
|
||||
/// <summary>
|
||||
/// DLT645_2007Address
|
||||
/// </summary>
|
||||
public class DLT645_2007Address : DeviceAddressBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public DLT645_2007Address()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据标识
|
||||
/// </summary>
|
||||
public byte[] DataId { get; set; } = new byte[0];
|
||||
/// <summary>
|
||||
/// 反转解析
|
||||
/// </summary>
|
||||
public bool Reverse { get; set; } = true;
|
||||
/// <summary>
|
||||
/// 站号信息
|
||||
/// </summary>
|
||||
public byte[] Station { get; set; } = new byte[0];
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 解析地址
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <returns></returns>
|
||||
public static DLT645_2007Address ParseFrom(string address)
|
||||
{
|
||||
DLT645_2007Address dLT645_2007Address = new();
|
||||
byte[] array;
|
||||
array = new byte[0];
|
||||
if (address.IndexOf(';') < 0)
|
||||
{
|
||||
array = address.ByHexStringToBytes().Reverse().ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
for (int index = 0; index < strArray.Length; ++index)
|
||||
{
|
||||
if (strArray[index].ToUpper().StartsWith("S="))
|
||||
{
|
||||
var station = strArray[index].Substring(2);
|
||||
if (station.IsNullOrEmpty()) station = string.Empty;
|
||||
if (station.Length < 12)
|
||||
station = station.PadLeft(12, '0');
|
||||
dLT645_2007Address.Station = station.ByHexStringToBytes().Reverse().ToArray();
|
||||
}
|
||||
else if (strArray[index].Contains("r="))
|
||||
{
|
||||
dLT645_2007Address.Reverse = strArray[index].Substring(2).GetBoolValue();
|
||||
}
|
||||
else if (!strArray[index].Contains("="))
|
||||
{
|
||||
array = strArray[index].ByHexStringToBytes().Reverse().ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
dLT645_2007Address.DataId = array;
|
||||
return dLT645_2007Address;
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder stringGeter = new();
|
||||
if (Station.Length > 0)
|
||||
{
|
||||
stringGeter.Append("s=" + Station.Reverse().ToArray().ToHexString() + ";");
|
||||
}
|
||||
if (DataId.Length > 0)
|
||||
{
|
||||
stringGeter.Append(DataId.Reverse().ToArray().ToHexString() + ";");
|
||||
}
|
||||
if (!Reverse)
|
||||
{
|
||||
stringGeter.Append("s=" + Reverse.ToString() + ";");
|
||||
}
|
||||
return stringGeter.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
public class DLT645_2007BitConverter : ThingsGatewayBitConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
public DLT645_2007BitConverter(EndianType endianType) : base(endianType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DLT645协议转换double
|
||||
/// </summary>
|
||||
/// <param name="buffer">带数据项标识</param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public override double ToDouble(byte[] buffer, int offset)
|
||||
{
|
||||
return Convert.ToDouble(this.ToString(buffer, offset, buffer.Length));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IThingsGatewayBitConverter CopyNew()
|
||||
{
|
||||
return new DLT645_2007BitConverter(EndianType)
|
||||
{
|
||||
DataFormat = DataFormat,
|
||||
BcdFormat = BcdFormat,
|
||||
Encoding = Encoding,
|
||||
IsStringReverseByteWord = IsStringReverseByteWord,
|
||||
Length = Length,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString(byte[] buffer)
|
||||
{
|
||||
return this.ToString(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString(byte[] buffer, int offset, int length)
|
||||
{
|
||||
buffer = buffer.RemoveBegin(offset);
|
||||
buffer = buffer.BytesAdd(-0x33);
|
||||
var dataInfos = DLT645Helper.GetDataInfos(buffer);
|
||||
StringBuilder stringBuilder = new();
|
||||
foreach (var dataInfo in dataInfos)
|
||||
{
|
||||
//实际数据
|
||||
var content = buffer.SelectMiddle(4, dataInfo.ByteLength).Reverse().ToArray();
|
||||
if (dataInfo.IsSigned)//可能为负数
|
||||
{
|
||||
if (content[0] > 0x80)//最高位是表示正负
|
||||
{
|
||||
content[0] = (byte)(content[0] - 0x80);
|
||||
if (dataInfo.Digtal == 0)//无小数点
|
||||
{
|
||||
stringBuilder.Append($"-{content.ToHexString()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append((-(Convert.ToDouble(content.ToHexString()) / Math.Pow(10.0, dataInfo.Digtal))).ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ToString(stringBuilder, dataInfo, content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ToString(stringBuilder, dataInfo, content);
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
|
||||
static void ToString(StringBuilder stringBuilder, DataInfo dataInfo, byte[] content)
|
||||
{
|
||||
if (dataInfo.Digtal < 0)
|
||||
{
|
||||
stringBuilder.Append($"{Encoding.ASCII.GetString(content)}");
|
||||
}
|
||||
else if (dataInfo.Digtal == 0)//无小数点
|
||||
{
|
||||
stringBuilder.Append($"{content.ToHexString()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append(((Convert.ToDouble(content.ToHexString()) / Math.Pow(10.0, dataInfo.Digtal))).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
|
||||
/// <summary>
|
||||
/// DLT645_2007DataHandleAdapter
|
||||
/// </summary>
|
||||
public class DLT645_2007DataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<DLT645_2007Message>
|
||||
{
|
||||
/// <summary>
|
||||
/// 增加FE FE FE FE的报文头部
|
||||
/// </summary>
|
||||
[Description("前导符报文头")]
|
||||
public bool EnableFEHead { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
//打包时加上4个FE字节
|
||||
if (EnableFEHead)
|
||||
{
|
||||
return DataTransUtil.SpliceArray(new byte[4] { 0xFE, 0xFE, 0xFE, 0xFE }, command);
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override DLT645_2007Message GetInstance()
|
||||
{
|
||||
return new DLT645_2007Message();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override FilterResult UnpackResponse(DLT645_2007Message request, byte[] send, byte[] body, byte[] response)
|
||||
{
|
||||
//因为设备可能带有FE前导符开头,这里找到0x68的位置
|
||||
int headCodeIndex = -1;
|
||||
if (response != null)
|
||||
{
|
||||
for (int index = 0; index < response.Length; index++)
|
||||
{
|
||||
if (response[index] == 0x68)
|
||||
{
|
||||
headCodeIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int sendHeadCodeIndex = 0;
|
||||
if (send != null)
|
||||
{
|
||||
for (int index = 0; index < send.Length; index++)
|
||||
{
|
||||
if (send[index] == 0x68)
|
||||
{
|
||||
sendHeadCodeIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//帧起始符 地址域 帧起始符 控制码 数据域长度共10个字节
|
||||
if (headCodeIndex < 0 || headCodeIndex + 10 > response.Length)
|
||||
return FilterResult.Cache;
|
||||
|
||||
|
||||
var len = 10 + response[headCodeIndex + 9] + 2;
|
||||
|
||||
if (response.Length - headCodeIndex < len)
|
||||
{
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
if (response.Length - headCodeIndex >= len && response[len + headCodeIndex - 1] == 0x16)
|
||||
{
|
||||
|
||||
//检查校验码
|
||||
int sumCheck = 0;
|
||||
for (int i = headCodeIndex; i < len + headCodeIndex - 2; i++)
|
||||
sumCheck += response[i];
|
||||
if ((byte)sumCheck != response[len + headCodeIndex - 2])
|
||||
{
|
||||
//校验错误
|
||||
request.Message = "和校验错误";
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
if (
|
||||
(response[headCodeIndex + 1] != send[sendHeadCodeIndex + 1]) ||
|
||||
(response[headCodeIndex + 2] != send[sendHeadCodeIndex + 2]) ||
|
||||
(response[headCodeIndex + 3] != send[sendHeadCodeIndex + 3]) ||
|
||||
(response[headCodeIndex + 4] != send[sendHeadCodeIndex + 4]) ||
|
||||
(response[headCodeIndex + 5] != send[sendHeadCodeIndex + 5]) ||
|
||||
(response[headCodeIndex + 6] != send[sendHeadCodeIndex + 6])
|
||||
)//设备地址不符合时,返回错误
|
||||
{
|
||||
|
||||
if (
|
||||
(send[sendHeadCodeIndex + 1] == 0xAA) &&
|
||||
(send[sendHeadCodeIndex + 2] == 0xAA) &&
|
||||
(send[sendHeadCodeIndex + 3] == 0xAA) &&
|
||||
(send[sendHeadCodeIndex + 4] == 0xAA) &&
|
||||
(send[sendHeadCodeIndex + 5] == 0xAA) &&
|
||||
(send[sendHeadCodeIndex + 6] == 0xAA)
|
||||
)//读写通讯地址例外
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Message = "返回地址不符合规则";
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((response[headCodeIndex + 8] != send[sendHeadCodeIndex + 8] + 0x80))//控制码不符合时,返回错误
|
||||
{
|
||||
request.Message = "返回控制码:" + $"0x{response[headCodeIndex + 8]:X2},请求控制码:" + $"0x{send[sendHeadCodeIndex + 8]:X2},不符合规则";
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if ((response[headCodeIndex + 8] & 0x40) == 0x40)//控制码bit6为1时,返回错误
|
||||
{
|
||||
byte byte1 = (byte)(response[headCodeIndex + 10] - 0x33);
|
||||
var error = DLT645Helper.Get2007ErrorMessage(byte1);
|
||||
request.Message = "异常控制码:" + $"0x{response[headCodeIndex + 8]:X2},错误信息:{error}";
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
if (send[sendHeadCodeIndex + 8] == (byte)ControlCode.Read ||
|
||||
send[sendHeadCodeIndex + 8] == (byte)ControlCode.Write
|
||||
)
|
||||
{
|
||||
//数据标识不符合时,返回错误
|
||||
if (
|
||||
(response[headCodeIndex + 10] == send[sendHeadCodeIndex + 10]) &&
|
||||
(response[headCodeIndex + 11] == send[sendHeadCodeIndex + 11]) &&
|
||||
(response[headCodeIndex + 12] == send[sendHeadCodeIndex + 12]) &&
|
||||
(response[headCodeIndex + 13] == send[sendHeadCodeIndex + 13])
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Message = "返回数据标识不符合规则";
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
request.Content = response.RemoveBegin(headCodeIndex + 10).RemoveLast(response.Length + 2 - len - headCodeIndex);
|
||||
request.ErrorCode = 0;
|
||||
return FilterResult.Success;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ErrorCode = 999;
|
||||
return FilterResult.Success;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class DLT645_2007Message : MessageBase, IMessage
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override int HeadBytesLength => -1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHeadBytes(byte[] head)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SendBytesThen()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,481 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
public class DLT645_2007OverTcp : ReadWriteDevicesTcpClientBase
|
||||
{
|
||||
/// <summary>
|
||||
/// DLT645_2007
|
||||
/// </summary>
|
||||
/// <param name="tcpClient"></param>
|
||||
public DLT645_2007OverTcp(TcpClient tcpClient) : base(tcpClient)
|
||||
{
|
||||
ThingsGatewayBitConverter = new DLT645_2007BitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加FE FE FE FE的报文头部
|
||||
/// </summary>
|
||||
[Description("前导符报文头")]
|
||||
public bool EnableFEHead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入需操作员代码
|
||||
/// </summary>
|
||||
[Description("操作员代码")]
|
||||
public string OperCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入密码
|
||||
/// </summary>
|
||||
[Description("写入密码")]
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通讯地址BCD码,一般应该是12个字符
|
||||
/// </summary>
|
||||
[Description("通讯地址")]
|
||||
public string Station { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
|
||||
var str = """
|
||||
查看附带文档或者相关资料,下面列举一下常见的数据标识地址
|
||||
|
||||
地址 说明
|
||||
-----------------------------------------
|
||||
02010100 A相电压
|
||||
02020100 A相电流
|
||||
02030000 瞬时总有功功率
|
||||
00000000 (当前)组合有功总电能
|
||||
00010000 (当前)正向有功总电能
|
||||
|
||||
""";
|
||||
return base.GetAddressDescription() + Environment.NewLine + str;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Read, Station);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
var dataHandleAdapter = new DLT645_2007DataHandleAdapter
|
||||
{
|
||||
EnableFEHead = EnableFEHead
|
||||
};
|
||||
TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, string value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
Password ??= string.Empty;
|
||||
OperCode ??= string.Empty;
|
||||
if (Password.Length < 8)
|
||||
Password = Password.PadLeft(8, '0');
|
||||
if (OperCode.Length < 8)
|
||||
OperCode = OperCode.PadLeft(8, '0');
|
||||
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
|
||||
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = WaitingClientEx.SendThenResponse(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default) => Write(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, string value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
Password ??= string.Empty;
|
||||
OperCode ??= string.Empty;
|
||||
if (Password.Length < 8)
|
||||
Password = Password.PadLeft(8, '0');
|
||||
if (OperCode.Length < 8)
|
||||
OperCode = OperCode.PadLeft(8, '0');
|
||||
var data = DataTransUtil.SpliceArray(Password.ByHexStringToBytes(), OperCode.ByHexStringToBytes());
|
||||
string[] strArray = value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command(address, (byte)ControlCode.Write, Station, data, strArray);
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, uint value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, double value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, float value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, long value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, ulong value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, ushort value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, short value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, int value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default) => WriteAsync(address, value.ToString(), cancellationToken);
|
||||
|
||||
|
||||
#region 其他方法
|
||||
|
||||
/// <summary>
|
||||
/// 广播校时
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public OperResult BroadcastTime(DateTime dateTime, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
string str = $"{dateTime.Second:D2}{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}{dateTime.Year % 100:D2}";
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.BroadcastTime, str.ByHexStringToBytes().Reverse().ToArray(), "999999999999".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
TcpClient.Send(commandResult.Content);
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 冻结
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> FreezeAsync(DateTime dateTime, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
string str = $"{dateTime.Minute:D2}{dateTime.Hour:D2}{dateTime.Day:D2}{dateTime.Month:D2}";
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.Freeze, str.ByHexStringToBytes().Reverse().ToArray(), Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 读取通信地址
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult<string>> ReadDeviceStationAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.ReadStation, null, "AAAAAAAAAAAA".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
var buffer = result1.Content.SelectMiddle(0, 6).BytesAdd(-0x33);
|
||||
return OperResult.CreateSuccessResult(buffer.Reverse().ToArray().ToHexString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<string>(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<string>(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 修改波特率
|
||||
/// </summary>
|
||||
/// <param name="baudRate"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WriteBaudRateAsync(int baudRate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
byte baudRateByte;
|
||||
switch (baudRate)
|
||||
{
|
||||
case 600: baudRateByte = 0x02; break;
|
||||
case 1200: baudRateByte = 0x04; break;
|
||||
case 2400: baudRateByte = 0x08; break;
|
||||
case 4800: baudRateByte = 0x10; break;
|
||||
case 9600: baudRateByte = 0x20; break;
|
||||
case 19200: baudRateByte = 0x40; break;
|
||||
default: return new OperResult<string>($"不支持此波特率:{baudRate}");
|
||||
}
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteBaudRate, new byte[] { baudRateByte }, Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新通信地址
|
||||
/// </summary>
|
||||
/// <param name="station"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WriteDeviceStationAsync(string station, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WriteStation, station.ByHexStringToBytes().Reverse().ToArray(), "AAAAAAAAAAAA".ByHexStringToBytes());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改密码
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="oldPassword"></param>
|
||||
/// <param name="newPassword"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OperResult> WritePasswordAsync(byte level, string oldPassword, string newPassword, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
|
||||
if (Station.IsNullOrEmpty()) Station = string.Empty;
|
||||
if (Station.Length < 12) Station = Station.PadLeft(12, '0');
|
||||
string str = $"04000C{level:D2}";
|
||||
|
||||
var commandResult = DLT645Helper.GetDLT645_2007Command((byte)ControlCode.WritePassword,
|
||||
str.ByHexStringToBytes().Reverse().ToArray()
|
||||
.SpliceArray(oldPassword.ByHexStringToBytes().Reverse().ToArray())
|
||||
.SpliceArray(newPassword.ByHexStringToBytes().Reverse().ToArray())
|
||||
, Station.ByHexStringToBytes().Reverse().ToArray());
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(commandResult.Content, TimeOut, cancellationToken);
|
||||
var result1 = ((MessageBase)result.RequestInfo);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(result1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult(commandResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<string>(ex);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
|
||||
|
||||
internal static class PackHelper
|
||||
{
|
||||
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
|
||||
{
|
||||
var byteConverter = device.ThingsGatewayBitConverter;
|
||||
var result = new List<T>();
|
||||
//需要先剔除额外信息,比如dataformat等
|
||||
foreach (var item in deviceVariables)
|
||||
{
|
||||
var address = item.VariableAddress;
|
||||
|
||||
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
|
||||
item.ThingsGatewayBitConverter = transformParameter;
|
||||
//item.VariableAddress = address;
|
||||
item.Index = device.GetBitOffset(item.VariableAddress);
|
||||
|
||||
result.Add(new()
|
||||
{
|
||||
DeviceVariableRunTimes = new() { item },
|
||||
VariableAddress = address,
|
||||
Length = 1,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
global using System;
|
||||
global using System.Linq;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
|
||||
global using ThingsGateway.Foundation.Serial;
|
||||
global using ThingsGateway.Foundation.Sockets;
|
||||
@@ -1,5 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,442 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>ThingsGateway.Foundation.Adapter.DLT645</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DataInfo">
|
||||
<summary>
|
||||
解析参数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.ByteLength">
|
||||
<summary>
|
||||
解析长度
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.Digtal">
|
||||
<summary>
|
||||
小数位
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DataInfo.IsSigned">
|
||||
<summary>
|
||||
有符号解析
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDataInfos(System.Byte[])">
|
||||
<summary>
|
||||
获取返回的解析信息
|
||||
</summary>
|
||||
<param name="buffer"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645Helper.GetDLT645_2007Command(System.String,System.Int32,System.Byte,System.String,System.Byte[],System.String[])">
|
||||
<summary>
|
||||
获取DLT645报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
<param name="serialSession"></param>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.EnableFEHead">
|
||||
<summary>
|
||||
增加FE FE FE FE的报文头部
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.OperCode">
|
||||
<summary>
|
||||
写入需操作员代码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Password">
|
||||
<summary>
|
||||
写入密码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.Station">
|
||||
<summary>
|
||||
通讯地址BCD码,一般应该是12个字符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.SetDataAdapter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
广播校时
|
||||
</summary>
|
||||
<param name="dateTime"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
冻结
|
||||
</summary>
|
||||
<param name="dateTime"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.ReadDeviceStationAsync(System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
读取通信地址
|
||||
</summary>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
修改波特率
|
||||
</summary>
|
||||
<param name="baudRate"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
更新通信地址
|
||||
</summary>
|
||||
<param name="station"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
修改密码
|
||||
</summary>
|
||||
<param name="level"></param>
|
||||
<param name="oldPassword"></param>
|
||||
<param name="newPassword"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.ControlCode">
|
||||
<summary>
|
||||
控制码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Read">
|
||||
<summary>
|
||||
读数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadSub">
|
||||
<summary>
|
||||
读后续数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.ReadStation">
|
||||
<summary>
|
||||
读站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Write">
|
||||
<summary>
|
||||
写数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteStation">
|
||||
<summary>
|
||||
写站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.BroadcastTime">
|
||||
<summary>
|
||||
广播校时
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.Freeze">
|
||||
<summary>
|
||||
冻结
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WriteBaudRate">
|
||||
<summary>
|
||||
更新波特率
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.DLT645.ControlCode.WritePassword">
|
||||
<summary>
|
||||
更新密码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address">
|
||||
<summary>
|
||||
DLT645_2007Address
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.UInt16)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.#ctor(System.String,System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.DataId">
|
||||
<summary>
|
||||
数据标识
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Reverse">
|
||||
<summary>
|
||||
反转解析
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Station">
|
||||
<summary>
|
||||
站号信息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.Parse(System.String,System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ParseFrom(System.String,System.Int32)">
|
||||
<summary>
|
||||
解析地址
|
||||
</summary>
|
||||
<param name="address"></param>
|
||||
<param name="length"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007Address.ToString">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.#ctor(ThingsGateway.Foundation.EndianType)">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToDouble(System.Byte[],System.Int32)">
|
||||
<summary>
|
||||
DLT645协议转换double
|
||||
</summary>
|
||||
<param name="buffer">带数据项标识</param>
|
||||
<param name="offset"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007BitConverter.ToString(System.Byte[],System.Int32,System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter">
|
||||
<summary>
|
||||
DLT645_2007DataHandleAdapter
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.EnableFEHead">
|
||||
<summary>
|
||||
增加FE FE FE FE的报文头部
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007DataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message,System.Byte[],System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.#ctor(ThingsGateway.Foundation.TcpClient)">
|
||||
<summary>
|
||||
DLT645_2007
|
||||
</summary>
|
||||
<param name="tcpClient"></param>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.EnableFEHead">
|
||||
<summary>
|
||||
增加FE FE FE FE的报文头部
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.OperCode">
|
||||
<summary>
|
||||
写入需操作员代码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Password">
|
||||
<summary>
|
||||
写入密码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.Station">
|
||||
<summary>
|
||||
通讯地址BCD码,一般应该是12个字符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.SetDataAdapter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.String,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Byte,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Double,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Single,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int64,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt64,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.UInt16,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int16,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.BroadcastTime(System.DateTime,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
广播校时
|
||||
</summary>
|
||||
<param name="dateTime"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.FreezeAsync(System.DateTime,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
冻结
|
||||
</summary>
|
||||
<param name="dateTime"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.ReadDeviceStationAsync(System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
读取通信地址
|
||||
</summary>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteBaudRateAsync(System.Int32,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
修改波特率
|
||||
</summary>
|
||||
<param name="baudRate"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WriteDeviceStationAsync(System.String,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
更新通信地址
|
||||
</summary>
|
||||
<param name="station"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.DLT645.DLT645_2007OverTcp.WritePasswordAsync(System.Byte,System.String,System.String,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
修改密码
|
||||
</summary>
|
||||
<param name="level"></param>
|
||||
<param name="oldPassword"></param>
|
||||
<param name="newPassword"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.HeadBytesLength">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.CheckHeadBytes(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.DLT645_2007Message.SendBytesThen">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,19 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
global using System;
|
||||
global using System.Linq;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
|
||||
global using ThingsGateway.Foundation.Serial;
|
||||
global using ThingsGateway.Foundation.Sockets;
|
||||
@@ -1,175 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension;
|
||||
using ThingsGateway.Foundation.Extension.String;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// Modbus协议地址
|
||||
/// </summary>
|
||||
public class ModbusAddress : DeviceAddressBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public ModbusAddress()
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 读取功能码
|
||||
/// </summary>
|
||||
public ushort AddressStart => Address.ToUShort();
|
||||
/// <summary>
|
||||
/// 读取功能码
|
||||
/// </summary>
|
||||
public byte ReadFunction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 站号信息
|
||||
/// </summary>
|
||||
public byte Station { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入功能码
|
||||
/// </summary>
|
||||
public byte WriteFunction { get; set; }
|
||||
/// <summary>
|
||||
/// 打包临时写入,需要读取的字节长度
|
||||
/// </summary>
|
||||
public int ByteLength { get; set; }
|
||||
/// <summary>
|
||||
/// BitIndex
|
||||
/// </summary>
|
||||
public int BitIndex => (int)(Address.SplitDot().LastOrDefault().ToInt());
|
||||
|
||||
/// <summary>
|
||||
/// 读取功能码
|
||||
/// </summary>
|
||||
public ushort AddressEnd => (ushort)(AddressStart + (Math.Ceiling(ByteLength / 2.0) > 0 ? Math.Ceiling(ByteLength / 2.0) : 1));
|
||||
|
||||
/// <summary>
|
||||
/// 作为Slave时需提供的SocketId,用于分辨Socket客户端,通常对比的是初始链接时的注册包
|
||||
/// </summary>
|
||||
public string SocketId { get; set; }
|
||||
/// <summary>
|
||||
/// 解析地址
|
||||
/// </summary>
|
||||
public static ModbusAddress ParseFrom(string address, byte station)
|
||||
{
|
||||
ModbusAddress modbusAddress = new()
|
||||
{
|
||||
Station = station
|
||||
};
|
||||
return ParseFrom(address, modbusAddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// 解析地址
|
||||
/// </summary>
|
||||
public static ModbusAddress ParseFrom(string address, ModbusAddress modbusAddress = null)
|
||||
{
|
||||
modbusAddress ??= new();
|
||||
if (address.IndexOf(';') < 0)
|
||||
{
|
||||
Address(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] strArray = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int index = 0; index < strArray.Length; ++index)
|
||||
{
|
||||
if (strArray[index].ToUpper().StartsWith("S="))
|
||||
{
|
||||
if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
|
||||
modbusAddress.Station = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
else if (strArray[index].ToUpper().StartsWith("W="))
|
||||
{
|
||||
if (Convert.ToInt16(strArray[index].Substring(2)) > 0)
|
||||
modbusAddress.WriteFunction = byte.Parse(strArray[index].Substring(2));
|
||||
}
|
||||
else if (strArray[index].ToUpper().StartsWith("ID="))
|
||||
{
|
||||
modbusAddress.SocketId = strArray[index].Substring(3);
|
||||
}
|
||||
else if (!strArray[index].Contains("="))
|
||||
{
|
||||
Address(strArray[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modbusAddress;
|
||||
|
||||
void Address(string address)
|
||||
{
|
||||
var readF = ushort.Parse(address.Substring(0, 1));
|
||||
if (readF > 4)
|
||||
throw new("功能码错误");
|
||||
switch (readF)
|
||||
{
|
||||
case 0:
|
||||
modbusAddress.ReadFunction = 1;
|
||||
break;
|
||||
case 1:
|
||||
modbusAddress.ReadFunction = 2;
|
||||
break;
|
||||
case 3:
|
||||
modbusAddress.ReadFunction = 4;
|
||||
break;
|
||||
case 4:
|
||||
modbusAddress.ReadFunction = 3;
|
||||
break;
|
||||
}
|
||||
modbusAddress.Address = (double.Parse(address.Substring(1)) - 1).ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder stringGeter = new();
|
||||
if (Station > 0)
|
||||
{
|
||||
stringGeter.Append("s=" + Station.ToString() + ";");
|
||||
}
|
||||
if (WriteFunction > 0)
|
||||
{
|
||||
stringGeter.Append("w=" + WriteFunction.ToString() + ";");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(SocketId))
|
||||
{
|
||||
stringGeter.Append("id=" + SocketId + ";");
|
||||
}
|
||||
stringGeter.Append(GetFunctionString(ReadFunction) + (AddressStart + 1).ToString());
|
||||
return stringGeter.ToString();
|
||||
}
|
||||
|
||||
private string GetFunctionString(int readF)
|
||||
{
|
||||
return readF switch
|
||||
{
|
||||
1 => "0",
|
||||
2 => "1",
|
||||
3 => "4",
|
||||
4 => "3",
|
||||
_ => "4",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Bool;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
internal class ModbusHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加Crc16
|
||||
/// </summary>
|
||||
internal static byte[] AddCrc(byte[] command)
|
||||
{
|
||||
return EasyCRC16.CRC16(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加ModbusTcp报文头
|
||||
/// </summary>
|
||||
internal static byte[] AddModbusTcpHead(byte[] modbus, ushort id)
|
||||
{
|
||||
byte[] tcp = new byte[modbus.Length + 6];
|
||||
tcp[0] = BitConverter.GetBytes(id)[1];
|
||||
tcp[1] = BitConverter.GetBytes(id)[0];
|
||||
tcp[4] = BitConverter.GetBytes(modbus.Length)[1];
|
||||
tcp[5] = BitConverter.GetBytes(modbus.Length)[0];
|
||||
modbus.CopyTo(tcp, 6);
|
||||
return tcp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// modbus地址格式说明
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetAddressDescription()
|
||||
{
|
||||
StringBuilder stringBuilder = new();
|
||||
stringBuilder.AppendLine("Modbus寄存器");
|
||||
stringBuilder.AppendLine("线圈寄存器使用从 00001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("离散输入寄存器使用从 10001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("输入寄存器使用从 30001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("保持寄存器使用从 40001 开始的地址编号。");
|
||||
stringBuilder.AppendLine("举例:");
|
||||
stringBuilder.AppendLine("40001=>保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("额外格式:");
|
||||
stringBuilder.AppendLine("设备站号 ,比如40001;s=2; ,代表设备地址为2的保持寄存器第一个寄存器");
|
||||
stringBuilder.AppendLine("写入功能码 ,比如40001;w=16; ,代表保持寄存器第一个寄存器,写入值时采用0x10功能码,而不是默认的0x06功能码");
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 通过错误码来获取到对应的文本消息
|
||||
/// </summary>
|
||||
internal static string GetDescriptionByErrorCode(byte code)
|
||||
{
|
||||
return code switch
|
||||
{
|
||||
1 => "不支持的功能码",
|
||||
2 => "读取寄存器越界",
|
||||
3 => "读取长度超限",
|
||||
4 => "读写异常",
|
||||
_ => "未知错误",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取modbus数据区内容,返回数据需去除Crc和报文头,例如:01 03 02 00 01,发送数据需报文头
|
||||
/// </summary>
|
||||
/// <param name="send">发送数据</param>
|
||||
/// <param name="response">返回数据</param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[], FilterResult> GetModbusData(byte[] send, byte[] response)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (response.Length < 3)
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
|
||||
if (response[1] >= 0x80)//错误码
|
||||
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
|
||||
if ((response.Length < response[2] + 3))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
|
||||
if (send.Length == 0)
|
||||
{
|
||||
var result = OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3), FilterResult.Success);
|
||||
result.Message = "接收数据正确,但主机并没有主动请求数据";
|
||||
return result;
|
||||
}
|
||||
if (send[0] != response[0])
|
||||
return new OperResult<byte[], FilterResult>(string.Format("站号不一致", send[0], response[0])) { Content2 = FilterResult.Success };
|
||||
if (send[1] != response[1])
|
||||
return new OperResult<byte[], FilterResult>() { Message = "功能码不一致", Content2 = FilterResult.Success };
|
||||
return OperResult.CreateSuccessResult(GenericExtensions.ArrayRemoveBegin(response, 3), FilterResult.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[], FilterResult>(ex.Message) { Content2 = FilterResult.Success };
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 去除Crc,返回modbus数据区
|
||||
/// </summary>
|
||||
/// <param name="send"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="crcCheck"></param>
|
||||
/// <returns></returns>
|
||||
internal static OperResult<byte[], FilterResult> GetModbusRtuData(byte[] send, byte[] response, bool crcCheck = true)
|
||||
{
|
||||
if (response.Length < 3)
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
if (response[1] >= 0x80)//错误码
|
||||
return new OperResult<byte[], FilterResult>(GetDescriptionByErrorCode(response[2])) { Content2 = FilterResult.Success };
|
||||
if ((response.Length < response[2] + 5))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
if (response[2] == 0)
|
||||
{
|
||||
if ((response.Length < 8))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
}
|
||||
|
||||
var data = response.SelectMiddle(0, response[2] != 0 ? response[2] + 5 : 8);
|
||||
if (crcCheck && !EasyCRC16.CheckCRC16(data))
|
||||
return new OperResult<byte[], FilterResult>("Crc校验失败" + DataTransUtil.ByteToHexString(data, ' ')) { Content2 = FilterResult.Success };
|
||||
return GetModbusData(send, data.RemoveLast(2));
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetReadModbusCommand(string address, int length, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mAddress = ModbusAddress.ParseFrom(address, station);
|
||||
return OperResult.CreateSuccessResult(GetReadModbusCommand(mAddress, length));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取写入布尔量报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool[] values, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mAddress = ModbusAddress.ParseFrom(address, station);
|
||||
|
||||
//功能码或实际长度
|
||||
if (values?.Length > 1 || mAddress.WriteFunction == 15)
|
||||
return GetWriteBoolModbusCommand(mAddress, values, values.Length);
|
||||
else
|
||||
return GetWriteBoolModbusCommand(address, values[0], station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取写入字报文,根据地址识别功能码
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteModbusCommand(string address, byte[] value, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mAddress = ModbusAddress.ParseFrom(address, station);
|
||||
|
||||
//功能码或实际长度
|
||||
if (value?.Length > 2 || mAddress.WriteFunction == 16)
|
||||
return OperResult.CreateSuccessResult(GetWriteModbusCommand(mAddress, value));
|
||||
else
|
||||
return OperResult.CreateSuccessResult(GetWriteOneModbusCommand(mAddress, value));
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取读取报文
|
||||
/// </summary>
|
||||
internal static byte[] GetReadModbusCommand(ModbusAddress mAddress, int length)
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
(byte) mAddress.Station,
|
||||
(byte) mAddress.ReadFunction,
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[1],
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[0],
|
||||
BitConverter.GetBytes(length)[1],
|
||||
BitConverter.GetBytes(length)[0]
|
||||
};
|
||||
return array;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteBoolModbusCommand(string address, bool value, byte station)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (address.IndexOf('.') <= 0)
|
||||
{
|
||||
var mAddress = ModbusAddress.ParseFrom(address, station);
|
||||
|
||||
return OperResult.CreateSuccessResult(GetWriteBoolModbusCommand(mAddress, value));
|
||||
}
|
||||
return new("不支持写入字寄存器的某一位");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取05写入布尔量报文
|
||||
/// </summary>
|
||||
private static byte[] GetWriteBoolModbusCommand(ModbusAddress mAddress, bool value)
|
||||
{
|
||||
byte[] array = new byte[6]
|
||||
{
|
||||
(byte) mAddress.Station,
|
||||
(byte)5,
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[1],
|
||||
BitConverter.GetBytes(mAddress.AddressStart)[0],
|
||||
0,
|
||||
0
|
||||
};
|
||||
if (value)
|
||||
{
|
||||
array[4] = 0xFF;
|
||||
array[5] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[4] = 0;
|
||||
array[5] = 0;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取15写入布尔量报文
|
||||
/// </summary>
|
||||
internal static OperResult<byte[]> GetWriteBoolModbusCommand(ModbusAddress mAddress, bool[] values, int length)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] numArray1 = values.BoolArrayToByte();
|
||||
byte[] numArray2 = new byte[7 + numArray1.Length];
|
||||
numArray2[0] = (byte)mAddress.Station;
|
||||
numArray2[1] = (byte)15;
|
||||
numArray2[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray2[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray2[4] = (byte)(length / 256);
|
||||
numArray2[5] = (byte)(length % 256);
|
||||
numArray2[6] = (byte)numArray1.Length;
|
||||
numArray1.CopyTo(numArray2, 7);
|
||||
return OperResult.CreateSuccessResult(numArray2);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取16写入字报文
|
||||
/// </summary>
|
||||
internal static byte[] GetWriteModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
{
|
||||
byte[] numArray = new byte[7 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)16;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
numArray[4] = (byte)(values.Length / 2 / 256);
|
||||
numArray[5] = (byte)(values.Length / 2 % 256);
|
||||
numArray[6] = (byte)values.Length;
|
||||
values.CopyTo(numArray, 7);
|
||||
return numArray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取6写入字报文
|
||||
/// </summary>
|
||||
internal static byte[] GetWriteOneModbusCommand(ModbusAddress mAddress, byte[] values)
|
||||
{
|
||||
byte[] numArray = new byte[4 + values.Length];
|
||||
numArray[0] = (byte)mAddress.Station;
|
||||
numArray[1] = (byte)6;
|
||||
numArray[2] = BitConverter.GetBytes(mAddress.AddressStart)[1];
|
||||
numArray[3] = BitConverter.GetBytes(mAddress.AddressStart)[0];
|
||||
values.CopyTo(numArray, 4);
|
||||
return numArray;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// ModbusRtu
|
||||
/// </summary>
|
||||
public class ModbusRtu : ReadWriteDevicesSerialSessionBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ModbusRtu
|
||||
/// </summary>
|
||||
/// <param name="serialSession"></param>
|
||||
public ModbusRtu(SerialSession serialSession) : base(serialSession)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crc校验
|
||||
/// </summary>
|
||||
[Description("Crc校验")]
|
||||
public bool Crc16CheckEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
Crc16CheckEnable = Crc16CheckEnable,
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// Rtu适配器
|
||||
/// </summary>
|
||||
public class ModbusRtuDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusRtuMessage>
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测CRC
|
||||
/// </summary>
|
||||
public bool Crc16CheckEnable { get; set; } = true;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return ModbusHelper.AddCrc(command);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusRtuMessage GetInstance()
|
||||
{
|
||||
return new ModbusRtuMessage();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override FilterResult UnpackResponse(ModbusRtuMessage request, byte[] send, byte[] body, byte[] response)
|
||||
{
|
||||
//链路干扰时需剔除前缀中的多于字节,初步按站号+功能码找寻初始字节
|
||||
if (send?.Length > 0)
|
||||
{
|
||||
int index = -1;
|
||||
for (int i = 0; i < response.Length - 1; i++)
|
||||
{
|
||||
if (response[i] == send[0] && (response[i + 1] == send[1] || response[i + 1] == (send[1] + 0x80)))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index >= 0)
|
||||
{
|
||||
response = response.RemoveBegin(index);
|
||||
}
|
||||
|
||||
//理想状态检测
|
||||
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
}
|
||||
return result.Content2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FilterResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusRtuMessage : MessageBase, IMessage
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override int HeadBytesLength => -1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHeadBytes(byte[] head)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SendBytesThen()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <inheritdoc/>
|
||||
public class ModbusRtuOverTcp : ReadWriteDevicesTcpClientBase
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ModbusRtuOverTcp(TcpClient tcpClient) : base(tcpClient)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crc校验
|
||||
/// </summary>
|
||||
[Description("Crc校验")]
|
||||
public bool Crc16CheckEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
ModbusRtuDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
Crc16CheckEnable = Crc16CheckEnable,
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ModbusRtuOverUdp : ReadWriteDevicesUdpSessionBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ModbusRtuOverUdp(UdpSession udpSession) : base(udpSession)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crc校验
|
||||
/// </summary>
|
||||
[Description("Crc校验")]
|
||||
public bool Crc16CheckEnable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
ModbusRtuOverUdpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
Crc16CheckEnable = Crc16CheckEnable,
|
||||
};
|
||||
UdpSession.Config.SetUdpDataHandlingAdapter(() =>
|
||||
{
|
||||
return dataHandleAdapter;
|
||||
});
|
||||
UdpSession.Setup(UdpSession.Config);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusRtuOverUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusRtuMessage>
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测CRC
|
||||
/// </summary>
|
||||
public bool Crc16CheckEnable { get; set; } = true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return ModbusHelper.AddCrc(command);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusRtuMessage GetInstance()
|
||||
{
|
||||
return new ModbusRtuMessage();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override OperResult<byte[]> UnpackResponse(byte[] send, byte[] response)
|
||||
{
|
||||
var result = ModbusHelper.GetModbusRtuData(send, response, Crc16CheckEnable);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,421 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Bool;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusSerialServer : ReadWriteDevicesSerialSessionBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
|
||||
/// </summary>
|
||||
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SerialSession, OperResult> WriteData;
|
||||
|
||||
/// <summary>
|
||||
/// 继电器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer01ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 开关输入
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer02ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 输入寄存器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer03ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 保持寄存器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer04ByteBlocks = new();
|
||||
/// <inheritdoc/>
|
||||
public ModbusSerialServer(SerialSession serialSession) : base(serialSession)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多站点
|
||||
/// </summary>
|
||||
public bool MulStation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认站点
|
||||
/// </summary>
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Dispose()
|
||||
{
|
||||
foreach (var item in ModbusServer01ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer02ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer03ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer04ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
ModbusServer01ByteBlocks.Clear();
|
||||
ModbusServer02ByteBlocks.Clear();
|
||||
ModbusServer03ByteBlocks.Clear();
|
||||
ModbusServer04ByteBlocks.Clear();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return new OperResult<byte[]>("地址错误");
|
||||
}
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
|
||||
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
|
||||
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
|
||||
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
|
||||
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
|
||||
int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 1:
|
||||
byte[] bytes0 = new byte[len];
|
||||
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer01ByteBlock.Read(bytes0);
|
||||
return OperResult.CreateSuccessResult(bytes0);
|
||||
case 2:
|
||||
byte[] bytes1 = new byte[len];
|
||||
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer02ByteBlock.Read(bytes1);
|
||||
return OperResult.CreateSuccessResult(bytes1);
|
||||
case 3:
|
||||
|
||||
byte[] bytes3 = new byte[len];
|
||||
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer03ByteBlock.Read(bytes3);
|
||||
return OperResult.CreateSuccessResult(bytes3);
|
||||
case 4:
|
||||
byte[] bytes4 = new byte[len];
|
||||
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer04ByteBlock.Read(bytes4);
|
||||
return OperResult.CreateSuccessResult(bytes4);
|
||||
}
|
||||
return new OperResult<byte[]>("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Read(address, length));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient)
|
||||
{
|
||||
ModbusSerialServerDataHandleAdapter dataHandleAdapter = new();
|
||||
dataHandleAdapter.CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout);
|
||||
SerialSession.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return new OperResult("地址错误");
|
||||
}
|
||||
Init(mAddress);
|
||||
}
|
||||
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
|
||||
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 3:
|
||||
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer03ByteBlock.Write(value);
|
||||
return OperResult.CreateSuccessResult();
|
||||
case 4:
|
||||
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer04ByteBlock.Write(value);
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
return new OperResult("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (new OperResult(ex));
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return (new OperResult("地址错误"));
|
||||
}
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
|
||||
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
|
||||
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 1:
|
||||
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
|
||||
return (OperResult.CreateSuccessResult());
|
||||
case 2:
|
||||
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
|
||||
return (OperResult.CreateSuccessResult());
|
||||
}
|
||||
return new OperResult("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Write(address, value));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Write(address, value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void Received(ByteBlock byteBlock, IRequestInfo requestInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
//接收外部报文
|
||||
if (requestInfo is ModbusSerialServerMessage modbusServerMessage)
|
||||
{
|
||||
if (modbusServerMessage.CurModbusAddress == null)
|
||||
{
|
||||
return;//无法解析直接返回
|
||||
}
|
||||
if (!modbusServerMessage.IsSuccess)
|
||||
{
|
||||
return;//无法解析直接返回
|
||||
}
|
||||
|
||||
if (modbusServerMessage.CurModbusAddress.WriteFunction == 0)//读取
|
||||
{
|
||||
var data = Read(modbusServerMessage.CurModbusAddress.ToString(), modbusServerMessage.Length);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
var coreData = data.Content;
|
||||
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
|
||||
{
|
||||
coreData = data.Content.Select(m => m > 0).ToArray().BoolArrayToByte().SelectMiddle(0, (int)Math.Ceiling(modbusServerMessage.Length / 8.0));
|
||||
}
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 2).SpliceArray(new byte[] { (byte)coreData.Length }, coreData);
|
||||
SerialSession.Send(sendData);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);//返回错误码
|
||||
}
|
||||
}
|
||||
else//写入
|
||||
{
|
||||
var coreData = modbusServerMessage.Content;
|
||||
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
|
||||
{
|
||||
//写入继电器
|
||||
if (WriteData != null)
|
||||
{
|
||||
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
|
||||
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(SerialSession, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//写入内存区
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(SerialSession, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//写入寄存器
|
||||
if (WriteData != null)
|
||||
{
|
||||
|
||||
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, SerialSession)).IsSuccess)
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(SerialSession, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(SerialSession, modbusServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(SerialSession, modbusServerMessage);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, ToString());
|
||||
}
|
||||
//返回错误码
|
||||
static void WriteError(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
|
||||
{
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 2)
|
||||
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
|
||||
sendData[1] = (byte)(sendData[1] + 128);
|
||||
SerialSession.Send(sendData);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteSuccess03(SerialSession SerialSession, ModbusSerialServerMessage modbusServerMessage)
|
||||
{
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 6);
|
||||
SerialSession.Send(sendData);
|
||||
}
|
||||
|
||||
private void Init(ModbusAddress mAddress)
|
||||
{
|
||||
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ModbusSerialServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusSerialServerMessage>
|
||||
{
|
||||
private readonly ThingsGatewayBitConverter ThingsGatewayBitConverter = new(EndianType.Big);
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return ModbusHelper.AddCrc(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取modbus写入数据区内容
|
||||
/// </summary>
|
||||
/// <param name="response">返回数据</param>
|
||||
/// <returns></returns>
|
||||
internal OperResult<byte[]> GetModbusData(byte[] response)
|
||||
{
|
||||
try
|
||||
{
|
||||
var func = ThingsGatewayBitConverter.ToByte(response, 1);
|
||||
if (func == 1 || func == 2 || func == 3 || func == 4 || func == 5 || func == 6)
|
||||
{
|
||||
if (response.Length == 6)
|
||||
return OperResult.CreateSuccessResult(response);
|
||||
}
|
||||
else if (func == 15 || func == 16)
|
||||
{
|
||||
var length = ThingsGatewayBitConverter.ToByte(response, 6);
|
||||
if (response.Length == 7 + length)
|
||||
{
|
||||
return OperResult.CreateSuccessResult(response);
|
||||
}
|
||||
}
|
||||
|
||||
return new OperResult<byte[]>() { Message = $"数据长度{response.Length}错误" };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusSerialServerMessage GetInstance()
|
||||
{
|
||||
return new ModbusSerialServerMessage();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override FilterResult UnpackResponse(ModbusSerialServerMessage request, byte[] send, byte[] body, byte[] response)
|
||||
{
|
||||
var result1 = ModbusHelper.GetModbusRtuData(new byte[0], response, true);
|
||||
if (result1.IsSuccess)
|
||||
{
|
||||
var result = GetModbusData(response.RemoveLast(2));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
//解析01 03 00 00 00 0A
|
||||
var station = ThingsGatewayBitConverter.ToByte(response, 0);
|
||||
var function = ThingsGatewayBitConverter.ToByte(response, 1);
|
||||
int addressStart = ThingsGatewayBitConverter.ToInt16(response, 2);
|
||||
if (addressStart == -1)
|
||||
{
|
||||
addressStart = 65535;
|
||||
}
|
||||
if (function > 4)
|
||||
{
|
||||
if (function > 6)
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
WriteFunction = function,
|
||||
ReadFunction = (byte)(function == 16 ? 3 : function == 15 ? 1 : 3),
|
||||
};
|
||||
request.Length = ThingsGatewayBitConverter.ToByte(response, 5);
|
||||
request.Content = result.Content.RemoveBegin(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
WriteFunction = function,
|
||||
ReadFunction = (byte)(function == 6 ? 3 : function == 5 ? 1 : 3),
|
||||
};
|
||||
request.Length = 1;
|
||||
request.Content = result.Content.RemoveBegin(4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
ReadFunction = function,
|
||||
};
|
||||
request.Length = ThingsGatewayBitConverter.ToByte(response, 5);
|
||||
}
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return result1.Content2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusSerialServerMessage : MessageBase, IMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前关联的地址
|
||||
/// </summary>
|
||||
public ModbusAddress CurModbusAddress { get; set; }
|
||||
/// <summary>
|
||||
/// 当前读写的数据长度
|
||||
/// </summary>
|
||||
public int Length { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int HeadBytesLength => -1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHeadBytes(byte[] head)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SendBytesThen()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <inheritdoc/>
|
||||
public class ModbusTcp : ReadWriteDevicesTcpClientBase
|
||||
{
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ModbusTcp(TcpClient tcpClient) : base(tcpClient)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
[Description("检测事务标识符")]
|
||||
public bool IsCheckMessageId { get; set; }
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
var data = SendThenReturn(commandResult, cancellationToken);
|
||||
return data;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
var data = await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
return data;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
IsCheckMessageId = IsCheckMessageId,
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
TcpClient.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// ModbusTcpDataHandleAdapter
|
||||
/// </summary>
|
||||
public class ModbusTcpDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusTcpMessage>
|
||||
{
|
||||
private readonly EasyIncrementCount easyIncrementCount = new(ushort.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
public bool IsCheckMessageId
|
||||
{
|
||||
get
|
||||
{
|
||||
return Request?.IsCheckMessageId ?? false;
|
||||
}
|
||||
set
|
||||
{
|
||||
Request.IsCheckMessageId = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return ModbusHelper.AddModbusTcpHead(command, (ushort)easyIncrementCount.GetCurrentValue());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusTcpMessage GetInstance()
|
||||
{
|
||||
return new ModbusTcpMessage();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override FilterResult UnpackResponse(ModbusTcpMessage request, byte[] send, byte[] body, byte[] response)
|
||||
{
|
||||
//理想状态检测
|
||||
var result = ModbusHelper.GetModbusData(send.RemoveBegin(6), response.RemoveBegin(6));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
request.Content = result.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
}
|
||||
return result.Content2;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusTcpMessage : MessageBase, IMessage
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override int HeadBytesLength => 6;
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
public bool IsCheckMessageId { get; set; } = false;
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHeadBytes(byte[] head)
|
||||
{
|
||||
if (head == null || head.Length <= 0) return false;
|
||||
HeadBytes = head;
|
||||
|
||||
int num = (HeadBytes[4] * 256) + HeadBytes[5];
|
||||
BodyLength = num;
|
||||
|
||||
if (!IsCheckMessageId)
|
||||
return true;
|
||||
else
|
||||
return SendBytes[0] == HeadBytes[0] && SendBytes[1] == HeadBytes[1] && HeadBytes[2] == 0 && HeadBytes[3] == 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <inheritdoc/>
|
||||
public class ModbusTcpDtu : ReadWriteDevicesTcpServerBase
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ModbusTcpDtu(TcpService tcpService) : base(tcpService)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
ModbusTcpDtuPlugin modbusTcpSalvePlugin = new ModbusTcpDtuPlugin();
|
||||
tcpService.Config.ConfigurePlugins(a =>
|
||||
{
|
||||
a.Add(modbusTcpSalvePlugin);
|
||||
});
|
||||
tcpService.Setup(tcpService.Config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
[Description("检测事务标识符")]
|
||||
public bool IsCheckMessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="e"></param>
|
||||
protected override void Connecting(SocketClient client, ConnectingEventArgs e)
|
||||
{
|
||||
Logger?.Debug(client.IP + ":" + client.Port + "正在连接");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
if (socketClient is SocketClient client)
|
||||
{
|
||||
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
IsCheckMessageId = IsCheckMessageId,
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
client.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in TcpService.GetClients())
|
||||
{
|
||||
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
IsCheckMessageId = IsCheckMessageId,
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
item.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(mAddress.SocketId, commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(string id, OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
|
||||
{
|
||||
SetDataAdapter(client);
|
||||
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var WaitingClientEx = client.GetWaitingClientEx(new() { BreakTrigger = true });
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>("客户端未连接");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(string id, OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
if (TcpService.TryGetSocketClient($"ID={id}", out var client))
|
||||
{
|
||||
SetDataAdapter(client);
|
||||
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var WaitingClientEx = client.GetWaitingClientEx(new() { BreakTrigger = true });
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>("客户端未连接");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal class ModbusTcpDtuPlugin : PluginBase, ITcpReceivingPlugin
|
||||
{
|
||||
public Task OnTcpReceiving(ITcpClientBase client, ByteBlockEventArgs e)
|
||||
{
|
||||
if (client is ISocketClient socket)
|
||||
{
|
||||
if (!socket.Id.StartsWith("ID="))
|
||||
{
|
||||
ByteBlock byteBlock = e.ByteBlock;
|
||||
var id = $"ID={byteBlock.ToArray().ToHexString()}";
|
||||
socket.ResetId(id);
|
||||
}
|
||||
}
|
||||
return e.InvokeNext();//如果本插件无法处理当前数据,请将数据转至下一个插件。
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,441 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Bool;
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusTcpServer : ReadWriteDevicesTcpServerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
|
||||
/// </summary>
|
||||
public Func<ModbusAddress, byte[], IThingsGatewayBitConverter, SocketClient, OperResult> WriteData;
|
||||
|
||||
/// <summary>
|
||||
/// 继电器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer01ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 开关输入
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer02ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 输入寄存器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer03ByteBlocks = new();
|
||||
|
||||
/// <summary>
|
||||
/// 保持寄存器
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<byte, ByteBlock> ModbusServer04ByteBlocks = new();
|
||||
/// <inheritdoc/>
|
||||
public ModbusTcpServer(TcpService tcpService) : base(tcpService)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多站点
|
||||
/// </summary>
|
||||
[Description("多站点")]
|
||||
public bool MulStation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认站点
|
||||
/// </summary>
|
||||
[Description("默认站点")]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Dispose()
|
||||
{
|
||||
foreach (var item in ModbusServer01ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer02ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer03ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
foreach (var item in ModbusServer04ByteBlocks)
|
||||
{
|
||||
item.Value.SafeDispose();
|
||||
}
|
||||
ModbusServer01ByteBlocks.Clear();
|
||||
ModbusServer02ByteBlocks.Clear();
|
||||
ModbusServer03ByteBlocks.Clear();
|
||||
ModbusServer04ByteBlocks.Clear();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return new OperResult<byte[]>("地址错误");
|
||||
}
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
|
||||
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
|
||||
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
|
||||
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
|
||||
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
|
||||
int len = mAddress.ReadFunction == 2 || mAddress.ReadFunction == 1 ? length : length * RegisterByteLength;
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 1:
|
||||
byte[] bytes0 = new byte[len];
|
||||
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer01ByteBlock.Read(bytes0);
|
||||
return OperResult.CreateSuccessResult(bytes0);
|
||||
case 2:
|
||||
byte[] bytes1 = new byte[len];
|
||||
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer02ByteBlock.Read(bytes1);
|
||||
return OperResult.CreateSuccessResult(bytes1);
|
||||
case 3:
|
||||
|
||||
byte[] bytes3 = new byte[len];
|
||||
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer03ByteBlock.Read(bytes3);
|
||||
return OperResult.CreateSuccessResult(bytes3);
|
||||
case 4:
|
||||
byte[] bytes4 = new byte[len];
|
||||
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer04ByteBlock.Read(bytes4);
|
||||
return OperResult.CreateSuccessResult(bytes4);
|
||||
}
|
||||
return new OperResult<byte[]>("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Read(address, length));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient)
|
||||
{
|
||||
if (socketClient is SocketClient client)
|
||||
{
|
||||
ModbusTcpServerDataHandleAdapter dataHandleAdapter = new();
|
||||
dataHandleAdapter.CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout);
|
||||
client.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in TcpService.GetClients())
|
||||
{
|
||||
ModbusTcpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
CacheTimeout = TimeSpan.FromMilliseconds(CacheTimeout)
|
||||
};
|
||||
item.SetDataHandlingAdapter(dataHandleAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return new OperResult("地址错误");
|
||||
}
|
||||
Init(mAddress);
|
||||
}
|
||||
var ModbusServer03ByteBlock = ModbusServer03ByteBlocks[mAddress.Station];
|
||||
var ModbusServer04ByteBlock = ModbusServer04ByteBlocks[mAddress.Station];
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 3:
|
||||
ModbusServer03ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer03ByteBlock.Write(value);
|
||||
return OperResult.CreateSuccessResult();
|
||||
case 4:
|
||||
ModbusServer04ByteBlock.Pos = mAddress.AddressStart * RegisterByteLength;
|
||||
ModbusServer04ByteBlock.Write(value);
|
||||
return OperResult.CreateSuccessResult();
|
||||
}
|
||||
return new OperResult("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ModbusAddress mAddress;
|
||||
try
|
||||
{
|
||||
mAddress = ModbusAddress.ParseFrom(address, Station);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (new OperResult(ex));
|
||||
}
|
||||
if (MulStation)
|
||||
{
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Station != mAddress.Station)
|
||||
{
|
||||
return (new OperResult("地址错误"));
|
||||
}
|
||||
Init(mAddress);
|
||||
|
||||
}
|
||||
|
||||
var ModbusServer01ByteBlock = ModbusServer01ByteBlocks[mAddress.Station];
|
||||
var ModbusServer02ByteBlock = ModbusServer02ByteBlocks[mAddress.Station];
|
||||
switch (mAddress.ReadFunction)
|
||||
{
|
||||
case 1:
|
||||
ModbusServer01ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer01ByteBlock.Write(value.BoolArrayToByte());
|
||||
return (OperResult.CreateSuccessResult());
|
||||
case 2:
|
||||
ModbusServer02ByteBlock.Pos = mAddress.AddressStart;
|
||||
ModbusServer02ByteBlock.Write(value.BoolArrayToByte());
|
||||
return (OperResult.CreateSuccessResult());
|
||||
}
|
||||
return new OperResult("功能码错误");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Write(address, value));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Write(address, value));
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void Received(SocketClient client, IRequestInfo requestInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
//接收外部报文
|
||||
if (requestInfo is ModbusTcpServerMessage modbusServerMessage)
|
||||
{
|
||||
if (modbusServerMessage.CurModbusAddress == null)
|
||||
{
|
||||
return;//无法解析直接返回
|
||||
}
|
||||
if (!modbusServerMessage.IsSuccess)
|
||||
{
|
||||
return;//无法解析直接返回
|
||||
}
|
||||
|
||||
if (modbusServerMessage.CurModbusAddress.WriteFunction == 0)//读取
|
||||
{
|
||||
var data = Read(modbusServerMessage.CurModbusAddress.ToString(), modbusServerMessage.Length);
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
var coreData = data.Content;
|
||||
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
|
||||
{
|
||||
coreData = data.Content.Select(m => m > 0).ToArray().BoolArrayToByte().SelectMiddle(0, (int)Math.Ceiling(modbusServerMessage.Length / 8.0));
|
||||
}
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 8).SpliceArray(new byte[] { (byte)coreData.Length }, coreData);
|
||||
sendData[5] = (byte)(sendData.Length - 6);
|
||||
client.Send(sendData);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);//返回错误码
|
||||
}
|
||||
}
|
||||
else//写入
|
||||
{
|
||||
var coreData = modbusServerMessage.Content;
|
||||
if (modbusServerMessage.CurModbusAddress.ReadFunction == 1 || modbusServerMessage.CurModbusAddress.ReadFunction == 2)
|
||||
{
|
||||
//写入继电器
|
||||
if (WriteData != null)
|
||||
{
|
||||
// 接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
|
||||
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(client, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//写入内存区
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData.ByteToBoolArray(modbusServerMessage.Length));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(client, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//写入寄存器
|
||||
if (WriteData != null)
|
||||
{
|
||||
|
||||
if ((WriteData(modbusServerMessage.CurModbusAddress, modbusServerMessage.Content, ThingsGatewayBitConverter, client)).IsSuccess)
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(client, modbusServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Write(modbusServerMessage.CurModbusAddress.ToString(), coreData);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
WriteSuccess03(client, modbusServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteError(client, modbusServerMessage);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, ToString());
|
||||
}
|
||||
//返回错误码
|
||||
static void WriteError(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
|
||||
{
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 8)
|
||||
.SpliceArray(new byte[] { (byte)1 });//01 lllegal function
|
||||
sendData[5] = (byte)(sendData.Length - 6);
|
||||
sendData[7] = (byte)(sendData[7] + 128);
|
||||
client.Send(sendData);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteSuccess03(SocketClient client, ModbusTcpServerMessage modbusServerMessage)
|
||||
{
|
||||
var sendData = modbusServerMessage.ReceivedBytes.SelectMiddle(0, 12);
|
||||
sendData[5] = (byte)(sendData.Length - 6);
|
||||
client.Send(sendData);
|
||||
}
|
||||
|
||||
private void Init(ModbusAddress mAddress)
|
||||
{
|
||||
if (ModbusServer01ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer01ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer02ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer02ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer03ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer03ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
if (ModbusServer04ByteBlocks.TryAdd(mAddress.Station, new(1024 * 128)))
|
||||
ModbusServer04ByteBlocks[mAddress.Station].SetLength(1024 * 128);
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ModbusTcpServerDataHandleAdapter : ReadWriteDevicesTcpDataHandleAdapter<ModbusTcpServerMessage>
|
||||
{
|
||||
private readonly ThingsGatewayBitConverter ThingsGatewayBitConverter = new(EndianType.Big);
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取modbus写入数据区内容
|
||||
/// </summary>
|
||||
/// <param name="response">返回数据</param>
|
||||
/// <returns></returns>
|
||||
internal OperResult<byte[]> GetModbusData(byte[] response)
|
||||
{
|
||||
try
|
||||
{
|
||||
var func = ThingsGatewayBitConverter.ToByte(response, 1);
|
||||
if (func == 1 || func == 2 || func == 3 || func == 4 || func == 5 || func == 6)
|
||||
{
|
||||
if (response.Length == 6)
|
||||
return OperResult.CreateSuccessResult(response);
|
||||
}
|
||||
else if (func == 15 || func == 16)
|
||||
{
|
||||
var length = ThingsGatewayBitConverter.ToByte(response, 6);
|
||||
if (response.Length == 7 + length)
|
||||
{
|
||||
return OperResult.CreateSuccessResult(response);
|
||||
}
|
||||
}
|
||||
|
||||
return new OperResult<byte[]>() { Message = $"数据长度{response.Length}错误" };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusTcpServerMessage GetInstance()
|
||||
{
|
||||
return new ModbusTcpServerMessage();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override FilterResult UnpackResponse(ModbusTcpServerMessage request, byte[] send, byte[] body, byte[] response)
|
||||
{
|
||||
var result = GetModbusData(response.RemoveBegin(6));
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
//解析01 03 00 00 00 0A
|
||||
var station = ThingsGatewayBitConverter.ToByte(response, 6);
|
||||
var function = ThingsGatewayBitConverter.ToByte(response, 7);
|
||||
int addressStart = ThingsGatewayBitConverter.ToInt16(response, 8);
|
||||
if (addressStart == -1)
|
||||
{
|
||||
addressStart = 65535;
|
||||
}
|
||||
if (function > 4)
|
||||
{
|
||||
if (function > 6)
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
WriteFunction = function,
|
||||
ReadFunction = (byte)(function == 16 ? 3 : function == 15 ? 1 : 3),
|
||||
};
|
||||
request.Length = ThingsGatewayBitConverter.ToByte(response, 11);
|
||||
request.Content = result.Content.RemoveBegin(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
WriteFunction = function,
|
||||
ReadFunction = (byte)(function == 6 ? 3 : function == 5 ? 1 : 3),
|
||||
};
|
||||
request.Length = 1;
|
||||
request.Content = result.Content.RemoveBegin(4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
request.CurModbusAddress = new ModbusAddress()
|
||||
{
|
||||
Station = station,
|
||||
Address = addressStart.ToString(),
|
||||
ReadFunction = function,
|
||||
};
|
||||
request.Length = ThingsGatewayBitConverter.ToByte(response, 11);
|
||||
}
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
return FilterResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ErrorCode = result.ErrorCode;
|
||||
request.Message = result.Message;
|
||||
return FilterResult.Cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusTcpServerMessage : MessageBase, IMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前关联的地址
|
||||
/// </summary>
|
||||
public ModbusAddress CurModbusAddress { get; set; }
|
||||
/// <summary>
|
||||
/// 当前读写的数据长度
|
||||
/// </summary>
|
||||
public int Length { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int HeadBytesLength => 6;
|
||||
/// <inheritdoc/>
|
||||
public override bool CheckHeadBytes(byte[] head)
|
||||
{
|
||||
if (head == null || head.Length != 6) return false;
|
||||
HeadBytes = head;
|
||||
|
||||
int num = (HeadBytes[4] * 256) + HeadBytes[5];
|
||||
BodyLength = num;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ModbusUdp : ReadWriteDevicesUdpSessionBase
|
||||
{
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ModbusUdp(UdpSession udpSession) : base(udpSession)
|
||||
{
|
||||
ThingsGatewayBitConverter = new ThingsGatewayBitConverter(EndianType.Big);
|
||||
RegisterByteLength = 2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
[Description("检测事务标识符")]
|
||||
public bool IsCheckMessageId { get; set; }
|
||||
/// <summary>
|
||||
/// 站号
|
||||
/// </summary>
|
||||
[Description("站号")]
|
||||
public byte Station { get; set; } = 1;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<T> LoadSourceRead<T, T2>(List<T2> deviceVariables, int maxPack)
|
||||
{
|
||||
return PackHelper.LoadSourceRead<T, T2>(this, deviceVariables, maxPack);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetAddressDescription()
|
||||
{
|
||||
return base.GetAddressDescription() + Environment.NewLine + ModbusHelper.GetAddressDescription();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override OperResult<byte[]> Read(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult<byte[]>> ReadAsync(string address, int length, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetReadModbusCommand(address, length, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult<byte[]>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetDataAdapter(object socketClient = null)
|
||||
{
|
||||
ModbusUdpDataHandleAdapter dataHandleAdapter = new()
|
||||
{
|
||||
IsCheckMessageId = IsCheckMessageId
|
||||
};
|
||||
UdpSession.Config.SetUdpDataHandlingAdapter(() =>
|
||||
{
|
||||
return dataHandleAdapter;
|
||||
});
|
||||
UdpSession.Setup(UdpSession.Config);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override OperResult Write(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connect(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return SendThenReturn(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, byte[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<OperResult> WriteAsync(string address, bool[] value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
var commandResult = ModbusHelper.GetWriteBoolModbusCommand(address, value, Station);
|
||||
return await SendThenReturnAsync(commandResult, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new OperResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private OperResult<byte[]> SendThenReturn(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
if (FrameTime != 0)
|
||||
Thread.Sleep(FrameTime);
|
||||
var result = WaitingClientEx.SendThenResponse(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<OperResult<byte[]>> SendThenReturnAsync(OperResult<byte[]> commandResult, CancellationToken cancellationToken)
|
||||
{
|
||||
if (commandResult.IsSuccess)
|
||||
{
|
||||
var item = commandResult.Content;
|
||||
await Task.Delay(FrameTime, cancellationToken);
|
||||
var result = await WaitingClientEx.SendThenResponseAsync(item, TimeOut, cancellationToken);
|
||||
return (MessageBase)result.RequestInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OperResult<byte[]>(commandResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public class ModbusUdpDataHandleAdapter : ReadWriteDevicesUdpDataHandleAdapter<ModbusTcpMessage>
|
||||
{
|
||||
private readonly EasyIncrementCount easyIncrementCount = new(ushort.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// 检测事务标识符
|
||||
/// </summary>
|
||||
public bool IsCheckMessageId
|
||||
{
|
||||
get
|
||||
{
|
||||
return Request?.IsCheckMessageId ?? false;
|
||||
}
|
||||
set
|
||||
{
|
||||
Request.IsCheckMessageId = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] PackCommand(byte[] command)
|
||||
{
|
||||
return ModbusHelper.AddModbusTcpHead(command, (ushort)easyIncrementCount.GetCurrentValue());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override ModbusTcpMessage GetInstance()
|
||||
{
|
||||
return new ModbusTcpMessage();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override OperResult<byte[]> UnpackResponse(byte[] send, byte[] response)
|
||||
{
|
||||
var result = ModbusHelper.GetModbusData(send.RemoveBegin(6), response.RemoveBegin(6));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ThingsGateway.Foundation.Extension.Generic;
|
||||
using ThingsGateway.Foundation.Extension.String;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// PackHelper
|
||||
/// </summary>
|
||||
public class PackHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 打包变量,添加到<see href="deviceVariableSourceReads"></see>
|
||||
/// </summary>
|
||||
/// <param name="device"></param>
|
||||
/// <param name="deviceVariables"></param>
|
||||
/// <param name="maxPack">最大打包长度</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> LoadSourceRead<T, T2>(IReadWrite device, List<T2> deviceVariables, int maxPack) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
|
||||
{
|
||||
if (deviceVariables == null)
|
||||
throw new ArgumentNullException(nameof(deviceVariables));
|
||||
|
||||
var deviceVariableSourceReads = new List<T>();
|
||||
var byteConverter = device.ThingsGatewayBitConverter;
|
||||
//需要先剔除额外信息,比如dataformat等
|
||||
foreach (var item in deviceVariables)
|
||||
{
|
||||
var address = item.VariableAddress;
|
||||
IThingsGatewayBitConverter transformParameter = ByteTransformUtil.GetTransByAddress(ref address, byteConverter);
|
||||
item.ThingsGatewayBitConverter = transformParameter;
|
||||
//item.VariableAddress = address;
|
||||
item.Index = device.GetBitOffset(item.VariableAddress);
|
||||
}
|
||||
var deviceVariableRunTimeGroups = deviceVariables.GroupBy(it => it.IntervalTime);
|
||||
foreach (var group in deviceVariableRunTimeGroups)
|
||||
{
|
||||
Dictionary<ModbusAddress, T2> map = group.ToDictionary(it =>
|
||||
{
|
||||
var lastLen = it.DataTypeEnum.GetByteLength();
|
||||
if (lastLen <= 0)
|
||||
{
|
||||
switch (it.DataTypeEnum)
|
||||
{
|
||||
case DataTypeEnum.String:
|
||||
lastLen = it.ThingsGatewayBitConverter.Length == null ? throw new("数据类型为字符串时,必须指定字符串长度,才能进行打包") : it.ThingsGatewayBitConverter.Length.Value;
|
||||
break;
|
||||
default:
|
||||
lastLen = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it.ThingsGatewayBitConverter.Length != null && it.DataTypeEnum != DataTypeEnum.String)
|
||||
{
|
||||
lastLen *= it.ThingsGatewayBitConverter.Length.Value;
|
||||
}
|
||||
|
||||
var address = it.VariableAddress;
|
||||
if (address.IndexOf('.') > 0)
|
||||
{
|
||||
var addressSplits = address.SplitDot();
|
||||
address = addressSplits.RemoveLast(1).ArrayToString(".");
|
||||
}
|
||||
var result = ModbusAddress.ParseFrom(address);
|
||||
result.ByteLength = lastLen;
|
||||
return result;
|
||||
});
|
||||
|
||||
//获取变量的地址
|
||||
var modbusAddressList = map.Keys;
|
||||
|
||||
//获取功能码
|
||||
var functionCodes = modbusAddressList.Select(t => t.ReadFunction).Distinct();
|
||||
foreach (var functionCode in functionCodes)
|
||||
{
|
||||
var modbusAddressSameFunList = modbusAddressList.Where(t => t.ReadFunction == functionCode);
|
||||
var stationNumbers = modbusAddressSameFunList.Select(t => t.Station).Distinct();
|
||||
foreach (var stationNumber in stationNumbers)
|
||||
{
|
||||
var addressList = modbusAddressSameFunList
|
||||
.Where(t => t.Station == stationNumber)
|
||||
.ToDictionary(t => t, t => map[t]);
|
||||
|
||||
var tempResult = LoadSourceRead<T, T2>(addressList, functionCode, group.Key, maxPack);
|
||||
deviceVariableSourceReads.AddRange(tempResult);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return deviceVariableSourceReads;
|
||||
}
|
||||
|
||||
private static List<T> LoadSourceRead<T, T2>(Dictionary<ModbusAddress, T2> addressList, int functionCode, int intervalTime, int maxPack) where T : IDeviceVariableSourceRead<IDeviceVariableRunTime>, new() where T2 : IDeviceVariableRunTime, new()
|
||||
{
|
||||
List<T> sourceReads = new();
|
||||
//按地址和长度排序
|
||||
var orderByAddressEnd = addressList.Keys.OrderBy(it => it.AddressEnd);
|
||||
//按地址和长度排序
|
||||
var orderByAddressStart = addressList.Keys.OrderBy(it => it.AddressStart);
|
||||
//地址最小,在循环中更改
|
||||
var minAddress = orderByAddressStart.First().AddressStart;
|
||||
//地址最大
|
||||
var maxAddress = orderByAddressStart.Last().AddressStart;
|
||||
|
||||
while (maxAddress >= minAddress)
|
||||
{
|
||||
//最大的打包长度
|
||||
int readLength = maxPack;
|
||||
if (functionCode == 1 || functionCode == 2)
|
||||
{
|
||||
readLength = maxPack * 8 * 2;
|
||||
}
|
||||
|
||||
|
||||
//获取当前的一组打包地址信息,
|
||||
var tempAddressEnd = orderByAddressEnd.Where(t => t.AddressEnd <= minAddress + readLength).ToList();
|
||||
//起始地址
|
||||
var startAddress = tempAddressEnd.OrderBy(it => it.AddressStart).First();
|
||||
//读取寄存器长度
|
||||
var sourceLen = tempAddressEnd.Last().AddressEnd - startAddress.AddressStart;
|
||||
|
||||
T sourceRead = new()
|
||||
{
|
||||
TimerTick = new TimerTick(intervalTime),
|
||||
//这里只需要根据地址排序的第一个地址,作为实际打包报文中的起始地址
|
||||
VariableAddress = startAddress.ToString(),
|
||||
Length = sourceLen
|
||||
};
|
||||
foreach (var item in tempAddressEnd)
|
||||
{
|
||||
var readNode = addressList[item];
|
||||
if ((functionCode == -1 || functionCode == 3 || functionCode == 4) && readNode.DataTypeEnum == DataTypeEnum.Boolean)
|
||||
{
|
||||
readNode.Index = ((item.AddressStart - startAddress.AddressStart) * 16) + readNode.Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (functionCode == 1 || functionCode == 2)
|
||||
readNode.Index = item.AddressStart - startAddress.AddressStart + readNode.Index;
|
||||
else
|
||||
readNode.Index = ((item.AddressStart - startAddress.AddressStart) * 2) + readNode.Index;
|
||||
}
|
||||
|
||||
sourceRead.DeviceVariableRunTimes.Add(readNode);
|
||||
addressList.Remove(item);
|
||||
}
|
||||
|
||||
sourceReads.Add(sourceRead);
|
||||
if (orderByAddressEnd.Count() > 0)
|
||||
minAddress = orderByAddressStart.First().AddressStart;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return sourceReads;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,611 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>ThingsGateway.Foundation.Adapter.Modbus</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress">
|
||||
<summary>
|
||||
Modbus协议地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.#ctor">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.AddressStart">
|
||||
<summary>
|
||||
读取功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ReadFunction">
|
||||
<summary>
|
||||
读取功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Station">
|
||||
<summary>
|
||||
站号信息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.WriteFunction">
|
||||
<summary>
|
||||
写入功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ByteLength">
|
||||
<summary>
|
||||
打包临时写入,需要读取的字节长度
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.AddressEnd">
|
||||
<summary>
|
||||
读取功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.Parse(System.String)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ParseFrom(System.String,System.Byte)">
|
||||
<summary>
|
||||
解析地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ParseFrom(System.String,ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress)">
|
||||
<summary>
|
||||
解析地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress.ToString">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.AddCrc(System.Byte[])">
|
||||
<summary>
|
||||
添加Crc16
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.AddModbusTcpHead(System.Byte[],System.UInt16)">
|
||||
<summary>
|
||||
添加ModbusTcp报文头
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetAddressDescription">
|
||||
<summary>
|
||||
modbus地址格式说明
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetDescriptionByErrorCode(System.Byte)">
|
||||
<summary>
|
||||
通过错误码来获取到对应的文本消息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetModbusData(System.Byte[],System.Byte[])">
|
||||
<summary>
|
||||
获取modbus数据区内容,返回数据需去除Crc和报文头,例如:01 03 02 00 01,发送数据需报文头
|
||||
</summary>
|
||||
<param name="send">发送数据</param>
|
||||
<param name="response">返回数据</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetModbusRtuData(System.Byte[],System.Byte[],System.Boolean)">
|
||||
<summary>
|
||||
去除Crc,返回modbus数据区
|
||||
</summary>
|
||||
<param name="send"></param>
|
||||
<param name="response"></param>
|
||||
<param name="crcCheck"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetReadModbusCommand(System.String,System.Int32,System.Byte)">
|
||||
<summary>
|
||||
获取读取报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteBoolModbusCommand(System.String,System.Boolean[],System.Byte)">
|
||||
<summary>
|
||||
获取写入布尔量报文,根据地址识别功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteModbusCommand(System.String,System.Byte[],System.Byte)">
|
||||
<summary>
|
||||
获取写入字报文,根据地址识别功能码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetReadModbusCommand(ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress,System.Int32)">
|
||||
<summary>
|
||||
获取读取报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteBoolModbusCommand(System.String,System.Boolean,System.Byte)">
|
||||
<summary>
|
||||
获取05写入布尔量报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteBoolModbusCommand(ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress,System.Boolean)">
|
||||
<summary>
|
||||
获取05写入布尔量报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteBoolModbusCommand(ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress,System.Boolean[],System.Int32)">
|
||||
<summary>
|
||||
获取15写入布尔量报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteModbusCommand(ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress,System.Byte[])">
|
||||
<summary>
|
||||
获取16写入字报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusHelper.GetWriteOneModbusCommand(ThingsGateway.Foundation.Adapter.Modbus.ModbusAddress,System.Byte[])">
|
||||
<summary>
|
||||
获取6写入字报文
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.#ctor(ThingsGateway.Foundation.Sockets.TcpClient)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Crc16CheckEnable">
|
||||
<summary>
|
||||
Crc校验
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Station">
|
||||
<summary>
|
||||
站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.#ctor(ThingsGateway.Foundation.Sockets.UdpSession)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Crc16CheckEnable">
|
||||
<summary>
|
||||
Crc校验
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Station">
|
||||
<summary>
|
||||
站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.Crc16CheckEnable">
|
||||
<summary>
|
||||
检测CRC
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuOverUdpDataHandleAdapter.UnpackResponse(System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu">
|
||||
<summary>
|
||||
ModbusRtu
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.#ctor(ThingsGateway.Foundation.Serial.SerialSession)">
|
||||
<summary>
|
||||
ModbusRtu
|
||||
</summary>
|
||||
<param name="serialSession"></param>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Crc16CheckEnable">
|
||||
<summary>
|
||||
Crc校验
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Station">
|
||||
<summary>
|
||||
站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtu.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter">
|
||||
<summary>
|
||||
Rtu适配器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.Crc16CheckEnable">
|
||||
<summary>
|
||||
检测CRC
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
<param name="command"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage,System.Byte[],System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.HeadBytesLength">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.CheckHeadBytes(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusRtuMessage.SendBytesThen">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ModbusServer01ByteBlocks">
|
||||
<summary>
|
||||
继电器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ModbusServer02ByteBlocks">
|
||||
<summary>
|
||||
开关输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ModbusServer03ByteBlocks">
|
||||
<summary>
|
||||
输入寄存器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ModbusServer04ByteBlocks">
|
||||
<summary>
|
||||
保持寄存器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteData">
|
||||
<summary>
|
||||
接收外部写入时,传出变量地址/写入字节组/转换规则/客户端
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.#ctor(ThingsGateway.Foundation.Sockets.TcpService)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.MulStation">
|
||||
<summary>
|
||||
多站点
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Station">
|
||||
<summary>
|
||||
默认站点
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Dispose">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServer.Received(ThingsGateway.Foundation.Sockets.SocketClient,ThingsGateway.Foundation.IRequestInfo)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
<param name="command"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.GetModbusData(System.Byte[])">
|
||||
<summary>
|
||||
获取modbus写入数据区内容
|
||||
</summary>
|
||||
<param name="response">返回数据</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage,System.Byte[],System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.CurModbusAddress">
|
||||
<summary>
|
||||
当前关联的地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.Length">
|
||||
<summary>
|
||||
当前读写的数据长度
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.HeadBytesLength">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusServerMessage.CheckHeadBytes(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.#ctor(ThingsGateway.Foundation.Sockets.TcpClient)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.IsCheckMessageId">
|
||||
<summary>
|
||||
检测事务标识符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Station">
|
||||
<summary>
|
||||
站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter">
|
||||
<summary>
|
||||
ModbusTcpDataHandleAdapter
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.IsCheckMessageId">
|
||||
<summary>
|
||||
检测事务标识符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpDataHandleAdapter.UnpackResponse(ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage,System.Byte[],System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.HeadBytesLength">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.IsCheckMessageId">
|
||||
<summary>
|
||||
检测事务标识符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusTcpMessage.CheckHeadBytes(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.#ctor(ThingsGateway.Foundation.Sockets.UdpSession)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.IsCheckMessageId">
|
||||
<summary>
|
||||
检测事务标识符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Station">
|
||||
<summary>
|
||||
站号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.LoadSourceRead``2(System.Collections.Generic.List{``1},System.Int32)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.GetAddressDescription">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Read(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.ReadAsync(System.String,System.Int32,System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.SetDataAdapter(System.Object)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Write(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.Write(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.WriteAsync(System.String,System.Byte[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdp.WriteAsync(System.String,System.Boolean[],System.Threading.CancellationToken)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.IsCheckMessageId">
|
||||
<summary>
|
||||
检测事务标识符
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.PackCommand(System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.GetInstance">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.ModbusUdpDataHandleAdapter.UnpackResponse(System.Byte[],System.Byte[])">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.Modbus.PackHelper">
|
||||
<summary>
|
||||
PackHelper
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.Modbus.PackHelper.ModbusLoadSourceRead``2(ThingsGateway.Foundation.IReadWrite,System.Collections.Generic.List{``1},System.Int32)">
|
||||
<summary>
|
||||
打包变量,添加到<see href="deviceVariableSourceReads"></see>
|
||||
</summary>
|
||||
<param name="device"></param>
|
||||
<param name="deviceVariables"></param>
|
||||
<param name="MaxPack">最大打包长度</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,371 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Comn;
|
||||
#pragma warning disable CA1416 // 验证平台兼容性
|
||||
#pragma warning disable IDE0090
|
||||
#pragma warning disable IDE0051
|
||||
|
||||
internal class ComInterop
|
||||
{
|
||||
private static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
|
||||
|
||||
#region const
|
||||
|
||||
private const uint EOAC_ACCESS_CONTROL = 0x04;
|
||||
private const uint EOAC_APPID = 0x08;
|
||||
private const uint EOAC_CLOAKING = 0x10;
|
||||
private const uint EOAC_DYNAMIC_CLOAKING = 0x40;
|
||||
private const uint EOAC_MUTUAL_AUTH = 0x01;
|
||||
private const uint EOAC_NONE = 0x00;
|
||||
private const uint EOAC_SECURE_REFS = 0x02;
|
||||
private const uint EOAC_STATIC_CLOAKING = 0x20;
|
||||
/// <summary>
|
||||
/// The WIN32 system default locale.
|
||||
/// </summary>
|
||||
private const int LOCALE_SYSTEM_DEFAULT = 0x800;
|
||||
|
||||
/// <summary>
|
||||
/// The WIN32 user default locale.
|
||||
/// </summary>
|
||||
private const int LOCALE_USER_DEFAULT = 0x400;
|
||||
|
||||
private const uint RPC_C_AUTHN_DCE_PRIVATE = 1;
|
||||
private const uint RPC_C_AUTHN_DCE_PUBLIC = 2;
|
||||
private const uint RPC_C_AUTHN_DEC_PUBLIC = 4;
|
||||
private const uint RPC_C_AUTHN_DEFAULT = 0xFFFFFFFF;
|
||||
private const uint RPC_C_AUTHN_DIGEST = 21;
|
||||
private const uint RPC_C_AUTHN_DPA = 17;
|
||||
private const uint RPC_C_AUTHN_GSS_KERBEROS = 16;
|
||||
private const uint RPC_C_AUTHN_GSS_NEGOTIATE = 9;
|
||||
private const uint RPC_C_AUTHN_GSS_SCHANNEL = 14;
|
||||
private const uint RPC_C_AUTHN_LEVEL_CALL = 3;
|
||||
private const uint RPC_C_AUTHN_LEVEL_CONNECT = 2;
|
||||
private const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0;
|
||||
private const uint RPC_C_AUTHN_LEVEL_NONE = 1;
|
||||
private const uint RPC_C_AUTHN_LEVEL_PKT = 4;
|
||||
private const uint RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5;
|
||||
private const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6;
|
||||
private const uint RPC_C_AUTHN_MQ = 100;
|
||||
private const uint RPC_C_AUTHN_MSN = 18;
|
||||
private const uint RPC_C_AUTHN_NONE = 0;
|
||||
private const uint RPC_C_AUTHN_WINNT = 10;
|
||||
private const uint RPC_C_AUTHZ_DCE = 2;
|
||||
private const uint RPC_C_AUTHZ_DEFAULT = 0xffffffff;
|
||||
private const uint RPC_C_AUTHZ_NAME = 1;
|
||||
private const uint RPC_C_AUTHZ_NONE = 0;
|
||||
private const uint RPC_C_IMP_LEVEL_ANONYMOUS = 1;
|
||||
private const uint RPC_C_IMP_LEVEL_DELEGATE = 4;
|
||||
private const uint RPC_C_IMP_LEVEL_IDENTIFY = 2;
|
||||
private const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3;
|
||||
#endregion const
|
||||
|
||||
#region struct
|
||||
|
||||
public struct COSERVERINFO
|
||||
{
|
||||
public uint dwReserved1;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pwszName;
|
||||
|
||||
public IntPtr pAuthInfo;
|
||||
public uint dwReserved2;
|
||||
};
|
||||
|
||||
public struct MULTI_QI
|
||||
{
|
||||
public IntPtr iid;
|
||||
|
||||
[MarshalAs(UnmanagedType.IUnknown)]
|
||||
public object pItf;
|
||||
|
||||
public uint hr;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct SOLE_AUTHENTICATION_SERVICE
|
||||
{
|
||||
public uint dwAuthnSvc;
|
||||
public uint dwAuthzSvc;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pPrincipalName;
|
||||
|
||||
public int hr;
|
||||
}
|
||||
|
||||
#endregion struct
|
||||
|
||||
#region win32 api
|
||||
|
||||
[DllImport("ole32.dll")]
|
||||
private static extern void CoCreateInstanceEx(ref Guid clsid,
|
||||
[MarshalAs(UnmanagedType.IUnknown)] object punkOuter,
|
||||
uint dwClsCtx,
|
||||
[In] ref COSERVERINFO pServerInfo,
|
||||
uint dwCount,
|
||||
[In, Out] MULTI_QI[] pResults);
|
||||
|
||||
[DllImport("ole32.dll")]
|
||||
private static extern int CoInitializeSecurity(
|
||||
IntPtr pSecDesc,
|
||||
int cAuthSvc,
|
||||
SOLE_AUTHENTICATION_SERVICE[] asAuthSvc,
|
||||
IntPtr pReserved1,
|
||||
uint dwAuthnLevel,
|
||||
uint dwImpLevel,
|
||||
IntPtr pAuthList,
|
||||
uint dwCapabilities,
|
||||
IntPtr pReserved3);
|
||||
|
||||
[DllImport("Kernel32.dll")]
|
||||
private static extern int FormatMessageW(
|
||||
int dwFlags,
|
||||
IntPtr lpSource,
|
||||
int dwMessageId,
|
||||
int dwLanguageId,
|
||||
IntPtr lpBuffer,
|
||||
int nSize,
|
||||
IntPtr Arguments);
|
||||
|
||||
[DllImport("Kernel32.dll")]
|
||||
private static extern int GetSystemDefaultLangID();
|
||||
|
||||
[DllImport("Kernel32.dll")]
|
||||
private static extern int GetUserDefaultLangID();
|
||||
#endregion win32 api
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个COM服务器的实例。
|
||||
/// </summary>
|
||||
public static object CreateInstance(Guid clsid, string hostName)
|
||||
{
|
||||
COSERVERINFO coserverInfo = new()
|
||||
{
|
||||
pwszName = hostName,
|
||||
pAuthInfo = IntPtr.Zero,
|
||||
dwReserved1 = 0,
|
||||
dwReserved2 = 0
|
||||
};
|
||||
|
||||
GCHandle hIID = GCHandle.Alloc(IID_IUnknown, GCHandleType.Pinned);
|
||||
|
||||
MULTI_QI[] results = new MULTI_QI[1];
|
||||
|
||||
results[0].iid = hIID.AddrOfPinnedObject();
|
||||
results[0].pItf = null;
|
||||
results[0].hr = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// 检查是否在本地或远程连接。
|
||||
uint clsctx = 0x01 | 0x04;
|
||||
|
||||
if (hostName != null && hostName.Length > 0 && hostName.ToLower() != "localhost" && hostName != "127.0.0.1")
|
||||
{
|
||||
clsctx = 0x04 | 0x10;
|
||||
}
|
||||
|
||||
// create an instance.
|
||||
CoCreateInstanceEx(
|
||||
ref clsid,
|
||||
null,
|
||||
clsctx,
|
||||
ref coserverInfo,
|
||||
1,
|
||||
results);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ExternalException("CoCreateInstanceEx: " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (hIID.IsAllocated) hIID.Free();
|
||||
}
|
||||
|
||||
if (results[0].hr != 0)
|
||||
{
|
||||
throw new ExternalException("CoCreateInstanceEx: " + GetSystemMessage((int)results[0].hr));
|
||||
}
|
||||
return results[0].pItf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定错误消息文本检索系统。
|
||||
/// </summary>
|
||||
internal static string GetSystemMessage(int error)
|
||||
{
|
||||
const int MAX_MESSAGE_LENGTH = 1024;
|
||||
const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
|
||||
const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
|
||||
|
||||
IntPtr buffer = Marshal.AllocCoTaskMem(MAX_MESSAGE_LENGTH);
|
||||
|
||||
_ = FormatMessageW(
|
||||
(int)(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM),
|
||||
IntPtr.Zero,
|
||||
error,
|
||||
0,
|
||||
buffer,
|
||||
MAX_MESSAGE_LENGTH - 1,
|
||||
IntPtr.Zero);
|
||||
|
||||
string msg = Marshal.PtrToStringUni(buffer);
|
||||
Marshal.FreeCoTaskMem(buffer);
|
||||
|
||||
if (!string.IsNullOrEmpty(msg))
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
return string.Format("0x{0,0:X}", error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化COM安全。
|
||||
/// </summary>
|
||||
internal static void InitializeSecurity()
|
||||
{
|
||||
int error = CoInitializeSecurity(
|
||||
IntPtr.Zero,
|
||||
-1,
|
||||
null,
|
||||
IntPtr.Zero,
|
||||
RPC_C_AUTHN_LEVEL_CONNECT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
IntPtr.Zero,
|
||||
EOAC_NONE,
|
||||
IntPtr.Zero);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
throw new ExternalException("COM初始化安全: " + GetSystemMessage(error), error);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 从枚举器读取guid。
|
||||
/// </summary>
|
||||
internal static Guid[] ReadClasses(IOPCEnumGUID enumerator)
|
||||
{
|
||||
List<Guid> guids = new List<Guid>();
|
||||
|
||||
int fetched = 0;
|
||||
Guid[] buffer = new Guid[10];
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr pGuids = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Guid)) * buffer.Length);
|
||||
|
||||
try
|
||||
{
|
||||
enumerator.Next(buffer.Length, pGuids, out fetched);
|
||||
|
||||
if (fetched > 0)
|
||||
{
|
||||
IntPtr pos = pGuids;
|
||||
|
||||
for (int ii = 0; ii < fetched; ii++)
|
||||
{
|
||||
object o = Marshal.PtrToStructure(pos, typeof(Guid));
|
||||
if (o != null)
|
||||
{
|
||||
buffer[ii] = (Guid)o;
|
||||
}
|
||||
pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Guid)));
|
||||
guids.Add(buffer[ii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pGuids);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (fetched > 0);
|
||||
|
||||
return guids.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从枚举器读取guid。
|
||||
/// </summary>
|
||||
internal static Guid[] ReadClasses(IEnumGUID enumerator)
|
||||
{
|
||||
List<Guid> guids = new List<Guid>();
|
||||
|
||||
int fetched = 0;
|
||||
Guid[] buffer = new Guid[10];
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr pGuids = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Guid)) * buffer.Length);
|
||||
|
||||
try
|
||||
{
|
||||
enumerator.Next(buffer.Length, pGuids, out fetched);
|
||||
|
||||
if (fetched > 0)
|
||||
{
|
||||
IntPtr pos = pGuids;
|
||||
|
||||
for (int ii = 0; ii < fetched; ii++)
|
||||
{
|
||||
object o = Marshal.PtrToStructure(pos, typeof(Guid));
|
||||
if (o != null)
|
||||
{
|
||||
buffer[ii] = (Guid)o;
|
||||
}
|
||||
pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Guid)));
|
||||
guids.Add(buffer[ii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pGuids);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (fetched > 0);
|
||||
|
||||
return guids.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放 COM 对象
|
||||
/// </summary>
|
||||
/// <param name="m_server"></param>
|
||||
internal static void RealseComServer(object m_server)
|
||||
{
|
||||
if (m_server != null && m_server.GetType().IsCOMObject)
|
||||
{
|
||||
Marshal.ReleaseComObject(m_server);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Comn;
|
||||
|
||||
internal static class Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// windows的filetime是从1601-1-1 00:00:00开始的,datetime是从1-1-1 00:00:00开始的
|
||||
/// datetime和filetime的滴答单位都是100ns(100纳秒,千万分之一秒),所以转换时只需要考虑开始时间即可
|
||||
/// </summary>
|
||||
private static readonly DateTime FILETIME_BaseTime = new DateTime(1601, 1, 1);
|
||||
|
||||
private static bool m_preserveUTC = false;
|
||||
|
||||
internal static object Clone(object source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (source.GetType().IsValueType)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
if (source.GetType().IsArray || source.GetType() == typeof(Array))
|
||||
{
|
||||
Array array = (Array)((Array)source).Clone();
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array.SetValue(Clone(array.GetValue(i)), i);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return ((ICloneable)source).Clone();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new NotSupportedException("Object cannot be cloned.");
|
||||
}
|
||||
}
|
||||
internal static DateTime FileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME filetime)
|
||||
{
|
||||
long num = filetime.dwHighDateTime;
|
||||
if (num < 0)
|
||||
{
|
||||
num += 4294967296L;
|
||||
}
|
||||
long num2 = num << 32;
|
||||
num = filetime.dwLowDateTime;
|
||||
if (num < 0)
|
||||
{
|
||||
num += 4294967296L;
|
||||
}
|
||||
num2 += num;
|
||||
if (num2 == 0)
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
if (m_preserveUTC)
|
||||
{
|
||||
DateTime fILETIME_BaseTime = FILETIME_BaseTime;
|
||||
return fILETIME_BaseTime.Add(new TimeSpan(num2));
|
||||
}
|
||||
DateTime fILETIME_BaseTime2 = FILETIME_BaseTime;
|
||||
return fILETIME_BaseTime2.Add(new TimeSpan(num2)).ToLocalTime();
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
|
||||
/// <summary>
|
||||
/// 值变化
|
||||
/// </summary>
|
||||
/// <param name="opcItems"></param>
|
||||
public delegate void OnDataChangedHandler(List<ItemReadResult> opcItems);
|
||||
/// <summary>
|
||||
/// 读取
|
||||
/// </summary>
|
||||
/// <param name="opcItems"></param>
|
||||
public delegate void OnReadCompletedHandler(List<ItemReadResult> opcItems);
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="opcItems"></param>
|
||||
internal delegate void OnWriteCompletedHandler(List<ItemWriteResult> opcItems);
|
||||
/// <summary>
|
||||
/// 返回结果
|
||||
/// </summary>
|
||||
public class ItemReadResult
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
/// <summary>
|
||||
/// Quality
|
||||
/// </summary>
|
||||
public short Quality { get; set; }
|
||||
/// <summary>
|
||||
/// TimeStamp
|
||||
/// </summary>
|
||||
public DateTime TimeStamp { get; set; }
|
||||
/// <summary>
|
||||
/// Value
|
||||
/// </summary>
|
||||
public object Value { get; set; } = 0;
|
||||
}
|
||||
|
||||
internal class ItemWriteResult
|
||||
{
|
||||
internal int Exception { get; set; } = 0;
|
||||
internal string Name { get; set; } = "";
|
||||
}
|
||||
@@ -1,457 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
#pragma warning disable CA1416 // 验证平台兼容性
|
||||
|
||||
internal class OpcGroup : IOPCDataCallback, IDisposable
|
||||
{
|
||||
internal object groupPointer = null;
|
||||
internal int revisedUpdateRate = 0;
|
||||
internal int serverGroupHandle = 0;
|
||||
private static int _handle = 0;
|
||||
private bool _bSubscribe = false;
|
||||
private bool disposedValue;
|
||||
private int lcid = 0x0;
|
||||
private IOPCAsyncIO2 m_Async2IO = null;
|
||||
private IConnectionPoint m_ConnectionPoint = null;
|
||||
private int m_connectionpoint_cookie = 0;
|
||||
private IConnectionPointContainer m_ConnectionPointContainer = null;
|
||||
private IOPCItemMgt m_ItemManagement = null;
|
||||
private IOPCGroupStateMgt m_StateManagement = null;
|
||||
private IOPCSyncIO m_SyncIO = null;
|
||||
private GCHandle percendDeadBand = GCHandle.Alloc(0, GCHandleType.Pinned);
|
||||
private GCHandle timeBias = GCHandle.Alloc(0, GCHandleType.Pinned);
|
||||
internal OpcGroup(string name)
|
||||
{
|
||||
Name = name;
|
||||
ClientGroupHandle = ++_handle;
|
||||
}
|
||||
|
||||
internal OpcGroup(string groupName, bool active, int reqUpdateRate, float deadBand)
|
||||
{
|
||||
Name = groupName;
|
||||
IsActive = active;
|
||||
RequestUpdateRate = reqUpdateRate;
|
||||
DeadBand = deadBand;
|
||||
ClientGroupHandle = ++_handle;
|
||||
}
|
||||
|
||||
internal delegate void CancelCompletedHandler(int dwTransid, int hGroup);
|
||||
|
||||
internal event CancelCompletedHandler OnCancelCompleted;
|
||||
|
||||
internal event OnDataChangedHandler OnDataChanged;
|
||||
|
||||
internal event OnReadCompletedHandler OnReadCompleted;
|
||||
|
||||
internal event OnWriteCompletedHandler OnWriteCompleted;
|
||||
|
||||
internal bool ActiveSubscribe
|
||||
{
|
||||
get
|
||||
{
|
||||
return _bSubscribe;
|
||||
}
|
||||
set
|
||||
{
|
||||
_bSubscribe = value;
|
||||
ActiveDataChanged(_bSubscribe);
|
||||
}
|
||||
}
|
||||
|
||||
internal int ClientGroupHandle { get; private set; }
|
||||
internal float DeadBand { get; set; } = 0.0f;
|
||||
internal object GroupPointer => groupPointer;
|
||||
|
||||
internal bool IsActive { get; set; } = true;
|
||||
internal int LCID
|
||||
{
|
||||
get => lcid;
|
||||
set => lcid = value;
|
||||
}
|
||||
|
||||
internal string Name { get; private set; } = string.Empty;
|
||||
internal List<OpcItem> OpcItems { get; private set; } = new List<OpcItem> { };
|
||||
internal GCHandle PercendDeadBand
|
||||
{
|
||||
get => percendDeadBand;
|
||||
set => percendDeadBand = value;
|
||||
}
|
||||
|
||||
internal int RequestUpdateRate { get; set; } = 1000;
|
||||
internal int RevisedUpdateRate => revisedUpdateRate;
|
||||
internal int ServerGroupHandle => serverGroupHandle;
|
||||
internal GCHandle TimeBias
|
||||
{
|
||||
get => timeBias;
|
||||
set => timeBias = value;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void OnCancelComplete(int dwTransid, int hGroup)
|
||||
{
|
||||
OnCancelCompleted?.Invoke(dwTransid, hGroup);
|
||||
}
|
||||
|
||||
public void OnDataChange(int dwTransid,
|
||||
int hGroup,
|
||||
int hrMasterquality,
|
||||
int hrMastererror,
|
||||
int dwCount,
|
||||
int[] phClientItems,
|
||||
object[] pvValues,
|
||||
short[] pwQualities,
|
||||
System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps,
|
||||
int[] pErrors)
|
||||
{
|
||||
List<ItemReadResult> itemChanged = new();
|
||||
for (int i = 0; i < dwCount; i++)
|
||||
{
|
||||
int index = OpcItems.FindIndex(x => x.ClientHandle == phClientItems[i]);
|
||||
if (index >= 0)
|
||||
{
|
||||
OpcItems[index].Value = pvValues[i];
|
||||
OpcItems[index].Quality = pwQualities[i];
|
||||
OpcItems[index].TimeStamp = Comn.Convert.FileTimeToDateTime(pftTimeStamps[i]);
|
||||
itemChanged.Add(new ItemReadResult
|
||||
{
|
||||
Name = OpcItems[index].ItemID,
|
||||
Value = pvValues[i],
|
||||
Quality = pwQualities[i],
|
||||
TimeStamp = OpcItems[index].TimeStamp
|
||||
});
|
||||
}
|
||||
}
|
||||
OnDataChanged?.Invoke(itemChanged);
|
||||
}
|
||||
|
||||
public void OnReadComplete(int dwTransid,
|
||||
int hGroup,
|
||||
int hrMasterquality,
|
||||
int hrMastererror,
|
||||
int dwCount,
|
||||
int[] phClientItems,
|
||||
object[] pvValues,
|
||||
short[] pwQualities,
|
||||
System.Runtime.InteropServices.ComTypes.FILETIME[] pftTimeStamps,
|
||||
int[] pErrors)
|
||||
{
|
||||
List<ItemReadResult> itemChanged = new();
|
||||
for (int i = 0; i < dwCount; i++)
|
||||
{
|
||||
int index = OpcItems.FindIndex(x => x.ClientHandle == phClientItems[i]);
|
||||
if (index >= 0)
|
||||
{
|
||||
OpcItems[index].Value = pvValues[i];
|
||||
OpcItems[index].Quality = pwQualities[i];
|
||||
OpcItems[index].TimeStamp = Comn.Convert.FileTimeToDateTime(pftTimeStamps[i]);
|
||||
itemChanged.Add(new ItemReadResult
|
||||
{
|
||||
Name = OpcItems[index].ItemID,
|
||||
Value = pvValues[i],
|
||||
Quality = pwQualities[i],
|
||||
TimeStamp = OpcItems[index].TimeStamp
|
||||
});
|
||||
}
|
||||
}
|
||||
OnReadCompleted?.Invoke(itemChanged);
|
||||
}
|
||||
|
||||
public void OnWriteComplete(int dwTransid,
|
||||
int hGroup,
|
||||
int hrMastererr,
|
||||
int dwCount,
|
||||
int[] pClienthandles,
|
||||
int[] pErrors)
|
||||
{
|
||||
List<ItemWriteResult> itemwrite = new();
|
||||
for (int i = 0; i < dwCount; i++)
|
||||
{
|
||||
int index = OpcItems.FindIndex(x => x.ClientHandle == pClienthandles[i]);
|
||||
if (index >= 0)
|
||||
{
|
||||
itemwrite.Add(new ItemWriteResult
|
||||
{
|
||||
Name = OpcItems[index].ItemID,
|
||||
Exception = pErrors[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
OnWriteCompleted?.Invoke(itemwrite);
|
||||
}
|
||||
|
||||
internal List<Tuple<OpcItem, int>> AddOpcItem(OpcItem[] items)
|
||||
{
|
||||
IntPtr pResults = IntPtr.Zero;
|
||||
IntPtr pErrors = IntPtr.Zero;
|
||||
OPCITEMDEF[] itemDefyArray = new OPCITEMDEF[items.Length];
|
||||
int i = 0;
|
||||
int[] errors = new int[items.Length];
|
||||
int[] itemServerHandle = new int[items.Length];
|
||||
try
|
||||
{
|
||||
foreach (OpcItem item in items)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
itemDefyArray[i].szAccessPath = item.AccessPath;
|
||||
itemDefyArray[i].szItemID = item.ItemID;
|
||||
itemDefyArray[i].bActive = item.IsActive ? 1 : 0;
|
||||
itemDefyArray[i].hClient = item.ClientHandle;
|
||||
itemDefyArray[i].dwBlobSize = item.BlobSize;
|
||||
itemDefyArray[i].pBlob = item.Blob;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
//添加OPC项组
|
||||
m_ItemManagement?.AddItems(items.Length, itemDefyArray, out pResults, out pErrors);
|
||||
IntPtr Pos = pResults;
|
||||
Marshal.Copy(pErrors, errors, 0, items.Length);
|
||||
List<Tuple<OpcItem, int>> results = new();
|
||||
for (int j = 0; j < items.Length; j++)
|
||||
{
|
||||
if (errors[j] == 0)
|
||||
{
|
||||
if (j != 0)
|
||||
{
|
||||
Pos = IntPtr.Add(Pos, Marshal.SizeOf(typeof(OPCITEMRESULT)));
|
||||
}
|
||||
object o = Marshal.PtrToStructure(Pos, typeof(OPCITEMRESULT));
|
||||
if (o != null)
|
||||
{
|
||||
var result = (OPCITEMRESULT)o;
|
||||
|
||||
items[j].RunTimeDataType = result.vtCanonicalDataType;
|
||||
itemServerHandle[j] = items[j].ServerHandle = result.hServer;
|
||||
Marshal.DestroyStructure(Pos, typeof(OPCITEMRESULT));
|
||||
OpcItems.Add(items[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
results.Add(Tuple.Create(items[j], errors[j]));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pResults != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pResults);
|
||||
}
|
||||
if (pErrors != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 建立连接
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
internal void InitIoInterfaces(object handle)
|
||||
{
|
||||
groupPointer = handle;
|
||||
m_ItemManagement = (IOPCItemMgt)groupPointer;
|
||||
m_Async2IO = (IOPCAsyncIO2)groupPointer;
|
||||
m_SyncIO = (IOPCSyncIO)groupPointer;
|
||||
m_StateManagement = (IOPCGroupStateMgt)groupPointer;
|
||||
m_ConnectionPointContainer = (IConnectionPointContainer)groupPointer;
|
||||
Guid iid = typeof(IOPCDataCallback).GUID;
|
||||
m_ConnectionPointContainer.FindConnectionPoint(ref iid, out m_ConnectionPoint);
|
||||
//创建客户端与服务端之间的连接
|
||||
m_ConnectionPoint.Advise(this, out m_connectionpoint_cookie);
|
||||
}
|
||||
/// <summary>
|
||||
/// 组读取
|
||||
/// </summary>
|
||||
/// <exception cref="ExternalException"></exception>
|
||||
internal void ReadAsync()
|
||||
{
|
||||
IntPtr pErrors = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
if (m_Async2IO != null)
|
||||
{
|
||||
int[] serverHandle = new int[OpcItems.Count];
|
||||
int[] PErrors = new int[OpcItems.Count];
|
||||
for (int j = 0; j < OpcItems.Count; j++)
|
||||
{
|
||||
serverHandle[j] = OpcItems[j].ServerHandle;
|
||||
}
|
||||
m_Async2IO.Read(OpcItems.Count, serverHandle, 2, out int cancelId, out pErrors);
|
||||
Marshal.Copy(pErrors, PErrors, 0, OpcItems.Count);
|
||||
if (PErrors.Any(a => a > 0))
|
||||
{
|
||||
throw new("读取错误,错误代码:" + pErrors);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new("连接无效");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pErrors != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal List<Tuple<OpcItem, int>> RemoveItem(OpcItem[] items)
|
||||
{
|
||||
IntPtr pErrors = IntPtr.Zero;
|
||||
int[] errors = new int[items.Length];
|
||||
int[] handles = new int[items.Length];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
handles[i] = items[i].ServerHandle;
|
||||
}
|
||||
try
|
||||
{
|
||||
m_ItemManagement?.RemoveItems(handles.Length, handles, out pErrors);
|
||||
Marshal.Copy(pErrors, errors, 0, items.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pErrors != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pErrors);
|
||||
}
|
||||
}
|
||||
List<Tuple<OpcItem, int>> results = new();
|
||||
for (int i = 0; i < errors.Length; i++)
|
||||
{
|
||||
if (errors[i] != 0)
|
||||
{
|
||||
results.Add(Tuple.Create(items[i], errors[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
OpcItems.Remove(items[i]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
internal List<Tuple<int, int>> Write(object[] values, int[] serverHandle)
|
||||
{
|
||||
IntPtr pErrors = IntPtr.Zero;
|
||||
var errors = new int[values.Length];
|
||||
if (m_Async2IO != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_SyncIO.Write(values.Length, serverHandle, values, out pErrors);
|
||||
Marshal.Copy(pErrors, errors, 0, values.Length);
|
||||
List<Tuple<int, int>> results = new();
|
||||
for (int i = 0; i < errors.Length; i++)
|
||||
{
|
||||
if (errors[i] != 0)
|
||||
{
|
||||
results.Add(Tuple.Create(serverHandle[i], errors[i]));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pErrors != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new("连接无效");
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (TimeBias.IsAllocated)
|
||||
{
|
||||
TimeBias.Free();
|
||||
}
|
||||
if (PercendDeadBand.IsAllocated)
|
||||
{
|
||||
PercendDeadBand.Free();
|
||||
}
|
||||
ActiveSubscribe = false;
|
||||
m_ConnectionPoint?.Unadvise(m_connectionpoint_cookie);
|
||||
m_connectionpoint_cookie = 0;
|
||||
if (null != m_ConnectionPoint) Marshal.ReleaseComObject(m_ConnectionPoint);
|
||||
m_ConnectionPoint = null;
|
||||
if (null != m_ConnectionPointContainer) Marshal.ReleaseComObject(m_ConnectionPointContainer);
|
||||
m_ConnectionPointContainer = null;
|
||||
if (m_Async2IO != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(m_Async2IO);
|
||||
m_Async2IO = null;
|
||||
}
|
||||
if (m_SyncIO != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(m_SyncIO);
|
||||
m_SyncIO = null;
|
||||
}
|
||||
if (m_StateManagement != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(m_StateManagement);
|
||||
m_StateManagement = null;
|
||||
}
|
||||
if (groupPointer != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(groupPointer);
|
||||
groupPointer = null;
|
||||
}
|
||||
m_ItemManagement = null;
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ActiveDataChanged(bool active)
|
||||
{
|
||||
IntPtr pRequestedUpdateRate = IntPtr.Zero;
|
||||
IntPtr hClientGroup = IntPtr.Zero;
|
||||
IntPtr pTimeBias = IntPtr.Zero;
|
||||
IntPtr pDeadband = IntPtr.Zero;
|
||||
IntPtr pLCID = IntPtr.Zero;
|
||||
int nActive = 0;
|
||||
GCHandle hActive = GCHandle.Alloc(nActive, GCHandleType.Pinned);
|
||||
hActive.Target = active ? 1 : 0;
|
||||
try
|
||||
{
|
||||
m_StateManagement?.SetState(pRequestedUpdateRate,
|
||||
out int nRevUpdateRate,
|
||||
hActive.AddrOfPinnedObject(),
|
||||
pTimeBias,
|
||||
pDeadband,
|
||||
pLCID,
|
||||
hClientGroup);
|
||||
}
|
||||
finally
|
||||
{
|
||||
hActive.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
/// <summary>
|
||||
/// OpcItem
|
||||
/// </summary>
|
||||
public class OpcItem
|
||||
{
|
||||
private static int _hanle = 0;
|
||||
/// <summary>
|
||||
/// OpcItem
|
||||
/// </summary>
|
||||
/// <param name="itemId"></param>
|
||||
public OpcItem(string itemId)
|
||||
{
|
||||
ItemID = itemId;
|
||||
ClientHandle = ++_hanle;
|
||||
}
|
||||
/// <summary>
|
||||
/// AccessPath
|
||||
/// </summary>
|
||||
public string AccessPath { get; private set; } = "";
|
||||
/// <summary>
|
||||
/// Blob
|
||||
/// </summary>
|
||||
public IntPtr Blob { get; set; } = IntPtr.Zero;
|
||||
/// <summary>
|
||||
/// BlobSize
|
||||
/// </summary>
|
||||
public int BlobSize { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// ClientHandle
|
||||
/// </summary>
|
||||
public int ClientHandle { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// active(1) or not(0)
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 数据项在opc server的完全名称
|
||||
/// </summary>
|
||||
public string ItemID { get; private set; } = String.Empty;
|
||||
/// <summary>
|
||||
/// Quality
|
||||
/// </summary>
|
||||
public int Quality { get; set; } = Qualities.OPC_QUALITY_BAD;
|
||||
/// <summary>
|
||||
/// RunTimeDataType
|
||||
/// </summary>
|
||||
public short RunTimeDataType { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// ServerHandle
|
||||
/// </summary>
|
||||
public int ServerHandle { get; set; }
|
||||
/// <summary>
|
||||
/// TimeStamp
|
||||
/// </summary>
|
||||
public DateTime TimeStamp { get; set; } = new DateTime(0);
|
||||
/// <summary>
|
||||
/// Value
|
||||
/// </summary>
|
||||
public object Value { get; set; }
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
#pragma warning disable CA1416 // 验证平台兼容性
|
||||
|
||||
internal class OpcServer : IDisposable
|
||||
{
|
||||
|
||||
private bool disposedValue;
|
||||
|
||||
private IOPCServer m_OpcServer = null;
|
||||
|
||||
internal OpcServer(string name, string host = "localhost")
|
||||
{
|
||||
Name = name;
|
||||
if (string.IsNullOrEmpty(host))
|
||||
{
|
||||
Host = "localhost";
|
||||
}
|
||||
else
|
||||
{
|
||||
Host = host;
|
||||
}
|
||||
}
|
||||
|
||||
internal string Host { get; private set; }
|
||||
internal bool IsConnected { get; private set; } = false;
|
||||
internal string Name { get; private set; }
|
||||
internal List<OpcGroup> OpcGroups { get; private set; } = new List<OpcGroup>(10);
|
||||
internal ServerStatus ServerStatus { get; private set; } = new ServerStatus();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
internal OpcGroup AddGroup(string groupName)
|
||||
{
|
||||
return AddGroup(groupName, true, 1000, 0);
|
||||
}
|
||||
|
||||
/// <returns></returns>
|
||||
internal OpcGroup AddGroup(string groupName, bool active, int reqUpdateRate, float deadBand)
|
||||
{
|
||||
if (null == m_OpcServer || IsConnected == false)
|
||||
throw new("未初始化连接!");
|
||||
OpcGroup group = new(groupName, active, reqUpdateRate, deadBand);
|
||||
Guid riid = typeof(IOPCItemMgt).GUID;
|
||||
m_OpcServer?.AddGroup(group.Name,
|
||||
group.IsActive ? 1 : 0,//IsActive
|
||||
group.RequestUpdateRate,//RequestedUpdateRate 1000ms
|
||||
group.ClientGroupHandle,
|
||||
group.TimeBias.AddrOfPinnedObject(),
|
||||
group.PercendDeadBand.AddrOfPinnedObject(),
|
||||
group.LCID,
|
||||
out group.serverGroupHandle,
|
||||
out group.revisedUpdateRate,
|
||||
ref riid,
|
||||
out group.groupPointer);
|
||||
if (group.groupPointer != null)
|
||||
{
|
||||
group.InitIoInterfaces(group.groupPointer);
|
||||
OpcGroups.Add(group);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new("添加OPC组错误,OPC服务器返回null");
|
||||
}
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点
|
||||
/// </summary>
|
||||
internal List<BrowseElement> Browse(string itemId = null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (null == m_OpcServer || IsConnected == false)
|
||||
throw new("未初始化连接!");
|
||||
|
||||
var count = 0;
|
||||
var moreElements = 0;
|
||||
|
||||
var pContinuationPoint = IntPtr.Zero;
|
||||
var pElements = IntPtr.Zero;
|
||||
var filterId = new PropertyID[]
|
||||
{
|
||||
new PropertyID(1),
|
||||
new PropertyID(3),
|
||||
new PropertyID(4),
|
||||
new PropertyID(5),
|
||||
new PropertyID(6),
|
||||
new PropertyID(101),
|
||||
};
|
||||
|
||||
|
||||
var server = m_OpcServer as IOPCBrowse;
|
||||
server.Browse(
|
||||
string.IsNullOrEmpty(itemId) ? "" : itemId,
|
||||
ref pContinuationPoint,
|
||||
int.MaxValue,
|
||||
OPCBROWSEFILTER.OPC_BROWSE_FILTER_ALL,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
1,
|
||||
filterId.Length,
|
||||
Interop.GetPropertyIDs(filterId),
|
||||
out moreElements,
|
||||
out count,
|
||||
out pElements);
|
||||
BrowseElement[] browseElements = Interop.GetBrowseElements(ref pElements, count, true);
|
||||
string stringUni = Marshal.PtrToStringUni(pContinuationPoint);
|
||||
Marshal.FreeCoTaskMem(pContinuationPoint);
|
||||
this.ProcessResults(browseElements, filterId);
|
||||
return browseElements?.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Connect()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Host) && !string.IsNullOrEmpty(Name))
|
||||
{
|
||||
var info = Discovery.OpcDiscovery.GetOpcServer(Name, Host);
|
||||
object o = Comn.ComInterop.CreateInstance(info.CLSID, Host);
|
||||
if (o == null)
|
||||
{
|
||||
throw new(string.Format("{0}{1}无法创建com对象", info.CLSID, Host));
|
||||
}
|
||||
m_OpcServer = (IOPCServer)o;
|
||||
IsConnected = true;
|
||||
}
|
||||
else
|
||||
throw new("应初始化Host与Name");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务器状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal ServerStatus GetServerStatus()
|
||||
{
|
||||
ServerStatus serverStatus = null;
|
||||
try
|
||||
{
|
||||
if (null == m_OpcServer || IsConnected == false)
|
||||
throw new("未初始化连接!");
|
||||
IntPtr statusPtr = IntPtr.Zero;
|
||||
m_OpcServer?.GetStatus(out statusPtr);
|
||||
OPCSERVERSTATUS status;
|
||||
if (statusPtr != IntPtr.Zero)
|
||||
{
|
||||
|
||||
object o = Marshal.PtrToStructure(statusPtr, typeof(OPCSERVERSTATUS));
|
||||
|
||||
Marshal.FreeCoTaskMem(statusPtr);
|
||||
|
||||
if (o != null)
|
||||
{
|
||||
status = (OPCSERVERSTATUS)o;
|
||||
serverStatus = new();
|
||||
serverStatus.Version = status.wMajorVersion.ToString() + "." + status.wMinorVersion.ToString() + "." + status.wBuildNumber.ToString();
|
||||
serverStatus.ServerState = status.dwServerState;
|
||||
serverStatus.StartTime = Comn.Convert.FileTimeToDateTime(status.ftStartTime);
|
||||
serverStatus.CurrentTime = Comn.Convert.FileTimeToDateTime(status.ftCurrentTime);
|
||||
serverStatus.LastUpdateTime = Comn.Convert.FileTimeToDateTime(status.ftLastUpdateTime);
|
||||
serverStatus.VendorInfo = status.szVendorInfo;
|
||||
IsConnected = true;
|
||||
|
||||
return serverStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsConnected = false;
|
||||
throw new("未知错误");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
IsConnected = false;
|
||||
throw new("未知错误");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (serverStatus != null)
|
||||
IsConnected = true;
|
||||
else
|
||||
IsConnected = false;
|
||||
ServerStatus = serverStatus;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal void RemoveGroup(OpcGroup group)
|
||||
{
|
||||
if (OpcGroups.Contains(group))
|
||||
{
|
||||
m_OpcServer?.RemoveGroup(group.ServerGroupHandle, 1);
|
||||
OpcGroups.Remove(group);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < OpcGroups.Count; i++)
|
||||
RemoveGroup(OpcGroups[i]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
if (m_OpcServer != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(m_OpcServer);
|
||||
m_OpcServer = null;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
OpcGroups.Clear();
|
||||
}
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessResults(BrowseElement[] elements, PropertyID[] propertyIDs)
|
||||
{
|
||||
if (elements == null)
|
||||
return;
|
||||
foreach (BrowseElement element in elements)
|
||||
{
|
||||
if (element.Properties != null)
|
||||
{
|
||||
foreach (ItemProperty property in element.Properties)
|
||||
{
|
||||
if (propertyIDs != null)
|
||||
{
|
||||
foreach (PropertyID propertyId in propertyIDs)
|
||||
{
|
||||
if (property.ID.Code == propertyId.Code)
|
||||
{
|
||||
property.ID = propertyId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
/// <summary>
|
||||
/// ServerStatus
|
||||
/// </summary>
|
||||
public class ServerStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// CurrentTime
|
||||
/// </summary>
|
||||
public DateTime CurrentTime { get; internal set; } = new DateTime(0);
|
||||
/// <summary>
|
||||
/// LastUpdateTime
|
||||
/// </summary>
|
||||
public DateTime LastUpdateTime { get; internal set; } = new DateTime(0);
|
||||
/// <summary>
|
||||
/// ServerState
|
||||
/// </summary>
|
||||
public OPCSERVERSTATE ServerState { get; internal set; } = OPCSERVERSTATE.OPC_STATUS_NOCONFIG;
|
||||
/// <summary>
|
||||
/// StartTime
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; internal set; } = new DateTime(0);
|
||||
/// <summary>
|
||||
/// VendorInfo
|
||||
/// </summary>
|
||||
public string VendorInfo { get; internal set; } = "UNKOWN";
|
||||
/// <summary>
|
||||
/// Version
|
||||
/// </summary>
|
||||
public string Version { get; internal set; } = "UNKOWN";
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Discovery;
|
||||
/// <summary>
|
||||
/// OpcDiscovery
|
||||
/// </summary>
|
||||
public class OpcDiscovery
|
||||
{
|
||||
private static readonly Guid CATID_OPC_DA10 = new("63D5F430-CFE4-11d1-B2C8-0060083BA1FB");
|
||||
|
||||
private static readonly Guid CATID_OPC_DA20 = new("63D5F432-CFE4-11d1-B2C8-0060083BA1FB");
|
||||
|
||||
private static readonly Guid CATID_OPC_DA30 = new("CC603642-66D7-48f1-B69A-B625E73652D7");
|
||||
|
||||
private static readonly Guid OPCEnumCLSID = new("13486D51-4821-11D2-A494-3CB306C10000");
|
||||
/// <summary>
|
||||
/// GetOpcServer
|
||||
/// </summary>
|
||||
/// <param name="serverName"></param>
|
||||
/// <param name="host"></param>
|
||||
/// <returns></returns>
|
||||
internal static ServerInfo GetOpcServer(string serverName, string host)
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(serverName))
|
||||
{
|
||||
throw new("检索失败,需提供OPCName");
|
||||
}
|
||||
ServerInfo result = null;
|
||||
ServerInfo[] serverInfos = null;
|
||||
object o_Server = Comn.ComInterop.CreateInstance(OPCEnumCLSID, host);
|
||||
if (o_Server == null)
|
||||
throw new("检索失败,请检查是否安装OPC Runtime");
|
||||
try
|
||||
{
|
||||
Guid catid = CATID_OPC_DA20;
|
||||
|
||||
//两种方式,兼容国产部分OPCServer不支持IOPCServerList2的情况
|
||||
try
|
||||
{
|
||||
IOPCServerList2 m_server2 = (IOPCServerList2)o_Server;
|
||||
GetIOPCServerList(ref result, ref serverInfos, serverName, host, m_server2, catid);
|
||||
if (result == null)
|
||||
{
|
||||
IOPCServerList m_server = (IOPCServerList)o_Server;
|
||||
GetIOPCServerList(ref result, ref serverInfos, serverName, host, m_server, catid);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
IOPCServerList m_server = (IOPCServerList)o_Server;
|
||||
GetIOPCServerList(ref result, ref serverInfos, serverName, host, m_server, catid);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var item in serverInfos)
|
||||
{
|
||||
sb.AppendLine(item.ToString());
|
||||
}
|
||||
throw new($"无法创建OPCServer连接,请检查OPC名称是否一致,以下为{host}中的OPC列表:"
|
||||
+ Environment.NewLine +
|
||||
sb.ToString()
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Comn.ComInterop.RealseComServer(o_Server);
|
||||
o_Server = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void GetIOPCServerList(ref ServerInfo result, ref ServerInfo[] serverInfos, string serverName, string host, IOPCServerList m_server, Guid catid)
|
||||
{
|
||||
object enumerator = null;
|
||||
//2
|
||||
m_server.EnumClassesOfCategories(
|
||||
1,
|
||||
new Guid[] { catid },
|
||||
0,
|
||||
null,
|
||||
out enumerator);
|
||||
Guid[] clsids = Comn.ComInterop.ReadClasses((IEnumGUID)enumerator);
|
||||
//释放
|
||||
Comn.ComInterop.RealseComServer(enumerator);
|
||||
enumerator = null;
|
||||
|
||||
serverInfos = GetServerDetails(clsids?.ToArray(), host, m_server);
|
||||
for (int i = 0; i < serverInfos.Length; i++)
|
||||
{
|
||||
if (serverInfos[i].CLSID.ToString().ToLower() == serverName.ToLower() ||
|
||||
serverInfos[i].ProgID.ToLower() == serverName.ToLower() ||
|
||||
serverInfos[i].VerIndProgID.ToLower() == serverName.ToLower())
|
||||
{
|
||||
result = serverInfos[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void GetIOPCServerList(ref ServerInfo result, ref ServerInfo[] serverInfos, string serverName, string host, IOPCServerList2 m_server, Guid catid)
|
||||
{
|
||||
//1
|
||||
IOPCEnumGUID enumerator = null;
|
||||
m_server.EnumClassesOfCategories(
|
||||
1,
|
||||
new Guid[] { catid },
|
||||
0,
|
||||
null,
|
||||
out enumerator);
|
||||
Guid[] clsids = Comn.ComInterop.ReadClasses(enumerator);
|
||||
//释放
|
||||
Comn.ComInterop.RealseComServer(enumerator);
|
||||
enumerator = null;
|
||||
|
||||
serverInfos = GetServerDetails(clsids?.ToArray(), host, m_server);
|
||||
for (int i = 0; i < serverInfos.Length; i++)
|
||||
{
|
||||
if (serverInfos[i].CLSID.ToString().ToLower() == serverName.ToLower() ||
|
||||
serverInfos[i].ProgID.ToLower() == serverName.ToLower() ||
|
||||
serverInfos[i].VerIndProgID.ToLower() == serverName.ToLower())
|
||||
{
|
||||
result = serverInfos[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static ServerInfo[] GetServerDetails(Guid[] clsids, string host, IOPCServerList m_server)
|
||||
{
|
||||
ArrayList servers = new ArrayList();
|
||||
for (int i = 0; i < clsids?.Length; i++)
|
||||
{
|
||||
Guid clsid = clsids[i];
|
||||
try
|
||||
{
|
||||
string progID = null;
|
||||
string description = null;
|
||||
string verIndProgID = null;
|
||||
ServerInfo server1 = new();
|
||||
|
||||
server1.Host = host;
|
||||
server1.CLSID = clsid;
|
||||
|
||||
m_server?.GetClassDetails(
|
||||
ref clsid,
|
||||
out progID,
|
||||
out description,
|
||||
out verIndProgID);
|
||||
if (verIndProgID != null)
|
||||
{
|
||||
server1.VerIndProgID = verIndProgID;
|
||||
}
|
||||
else if (progID != null)
|
||||
{
|
||||
server1.ProgID = progID;
|
||||
}
|
||||
if (description != null)
|
||||
{
|
||||
server1.Description = description;
|
||||
}
|
||||
servers.Add(server1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return (ServerInfo[])servers.ToArray(typeof(ServerInfo));
|
||||
}
|
||||
|
||||
private static ServerInfo[] GetServerDetails(Guid[] clsids, string host, IOPCServerList2 m_server)
|
||||
{
|
||||
ArrayList servers = new ArrayList();
|
||||
for (int i = 0; i < clsids?.Length; i++)
|
||||
{
|
||||
Guid clsid = clsids[i];
|
||||
try
|
||||
{
|
||||
string progID = null;
|
||||
string description = null;
|
||||
string verIndProgID = null;
|
||||
ServerInfo server1 = new();
|
||||
|
||||
server1.Host = host;
|
||||
server1.CLSID = clsid;
|
||||
|
||||
m_server?.GetClassDetails(
|
||||
ref clsid,
|
||||
out progID,
|
||||
out description,
|
||||
out verIndProgID);
|
||||
if (verIndProgID != null)
|
||||
{
|
||||
server1.VerIndProgID = verIndProgID;
|
||||
}
|
||||
else if (progID != null)
|
||||
{
|
||||
server1.ProgID = progID;
|
||||
}
|
||||
if (description != null)
|
||||
{
|
||||
server1.Description = description;
|
||||
}
|
||||
servers.Add(server1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return (ServerInfo[])servers.ToArray(typeof(ServerInfo));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
internal class ServerInfo
|
||||
{
|
||||
internal Guid CLSID { get; set; }
|
||||
internal string Description { get; set; } = string.Empty;
|
||||
internal string Host { get; set; } = string.Empty;
|
||||
internal string ProgID { get; set; } = string.Empty;
|
||||
internal string VerIndProgID { get; set; } = string.Empty;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.AppendLine($"{nameof(CLSID)}:{CLSID}");
|
||||
stringBuilder.AppendLine($"{nameof(Description)}:{Description}");
|
||||
stringBuilder.AppendLine($"{nameof(Host)}:{Host}");
|
||||
stringBuilder.AppendLine($"{nameof(ProgID)}:{ProgID}");
|
||||
stringBuilder.AppendLine($"{nameof(VerIndProgID)}:{VerIndProgID}");
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
|
||||
[Serializable]
|
||||
public class BrowseElement : ICloneable
|
||||
{
|
||||
private bool m_hasChildren;
|
||||
private bool m_isItem;
|
||||
private string m_itemName;
|
||||
private string m_itemPath;
|
||||
private string m_name;
|
||||
private ItemProperty[] m_properties = new ItemProperty[0];
|
||||
|
||||
public bool HasChildren
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_hasChildren;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_hasChildren = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_isItem;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_isItem = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ItemName
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_itemName;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_itemName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ItemPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_itemPath;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_itemPath = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_name = value;
|
||||
}
|
||||
}
|
||||
public ItemProperty[] Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_properties;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_properties = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object Clone()
|
||||
{
|
||||
BrowseElement obj = (BrowseElement)MemberwiseClone();
|
||||
obj.m_properties = (ItemProperty[])Comn.Convert.Clone(m_properties);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -1,333 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.
|
||||
|
||||
Runtime.InteropServices;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("B196B286-BAB4-101A-B69C-00AA00341D07")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IConnectionPoint
|
||||
{
|
||||
void GetConnectionInterface(
|
||||
[Out]
|
||||
out Guid pIID);
|
||||
|
||||
void GetConnectionPointContainer(
|
||||
[Out]
|
||||
out IConnectionPointContainer ppCPC);
|
||||
|
||||
void Advise(
|
||||
[MarshalAs(UnmanagedType.IUnknown)]
|
||||
object pUnkSink,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pdwCookie);
|
||||
|
||||
void Unadvise(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int dwCookie);
|
||||
|
||||
void EnumConnections(
|
||||
[Out]
|
||||
out IEnumConnections ppEnum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("B196B284-BAB4-101A-B69C-00AA00341D07")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IConnectionPointContainer
|
||||
{
|
||||
void EnumConnectionPoints(
|
||||
[Out]
|
||||
out IEnumConnectionPoints ppEnum);
|
||||
|
||||
void FindConnectionPoint(
|
||||
ref Guid riid,
|
||||
[Out]
|
||||
out IConnectionPoint ppCP);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("B196B285-BAB4-101A-B69C-00AA00341D07")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IEnumConnectionPoints
|
||||
{
|
||||
void RemoteNext(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cConnections,
|
||||
[Out]
|
||||
IntPtr ppCP,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pcFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cConnections);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IEnumConnectionPoints ppEnum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("B196B287-BAB4-101A-B69C-00AA00341D07")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IEnumConnections
|
||||
{
|
||||
void RemoteNext(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cConnections,
|
||||
[Out]
|
||||
IntPtr rgcd,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pcFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cConnections);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IEnumConnections ppEnum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("0002E000-0000-0000-C000-000000000046")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IEnumGUID
|
||||
{
|
||||
void Next(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt,
|
||||
[Out]
|
||||
IntPtr rgelt,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pceltFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IEnumGUID ppenum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("00000101-0000-0000-C000-000000000046")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IEnumString
|
||||
{
|
||||
[PreserveSig]
|
||||
int RemoteNext(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt,
|
||||
IntPtr rgelt,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pceltFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IEnumString ppenum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("00000100-0000-0000-C000-000000000046")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IEnumUnknown
|
||||
{
|
||||
void RemoteNext(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt,
|
||||
[Out]
|
||||
IntPtr rgelt,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pceltFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IEnumUnknown ppenum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("F31DFDE2-07B6-11d2-B2D8-0060083BA1FB")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOPCCommon
|
||||
{
|
||||
void SetLocaleID(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int dwLcid);
|
||||
|
||||
void GetLocaleID(
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pdwLcid);
|
||||
|
||||
void QueryAvailableLocaleIDs(
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pdwCount,
|
||||
[Out]
|
||||
out IntPtr pdwLcid);
|
||||
|
||||
void GetErrorString(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int dwError,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out String ppString);
|
||||
|
||||
void SetClientName(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
String szName);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("55C382C8-21C7-4e88-96C1-BECFB1E3F483")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOPCEnumGUID
|
||||
{
|
||||
void Next(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt,
|
||||
[Out]
|
||||
IntPtr rgelt,
|
||||
[Out][MarshalAs(UnmanagedType.I4)]
|
||||
out int pceltFetched);
|
||||
|
||||
void Skip(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
void Clone(
|
||||
[Out]
|
||||
out IOPCEnumGUID ppenum);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("13486D50-4821-11D2-A494-3CB306C10000")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOPCServerList
|
||||
{
|
||||
void EnumClassesOfCategories(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cImplemented,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)]
|
||||
Guid[] rgcatidImpl,
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cRequired,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=2)]
|
||||
Guid[] rgcatidReq,
|
||||
[Out][MarshalAs(UnmanagedType.IUnknown)]
|
||||
out object ppenumClsid);
|
||||
|
||||
void GetClassDetails(
|
||||
ref Guid clsid,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszProgID,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszUserType,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszVerIndProgID);
|
||||
|
||||
void CLSIDFromProgID(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string szProgId,
|
||||
[Out]
|
||||
out Guid clsid);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("9DD0B56C-AD9E-43ee-8305-487F3188BF7A")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOPCServerList2
|
||||
{
|
||||
void EnumClassesOfCategories(
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cImplemented,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)]
|
||||
Guid[] rgcatidImpl,
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int cRequired,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStruct, SizeParamIndex=0)]
|
||||
Guid[] rgcatidReq,
|
||||
[Out]
|
||||
out IOPCEnumGUID ppenumClsid);
|
||||
|
||||
void GetClassDetails(
|
||||
ref Guid clsid,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszProgID,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszUserType,
|
||||
[Out][MarshalAs(UnmanagedType.LPWStr)]
|
||||
out string ppszVerIndProgID);
|
||||
|
||||
void CLSIDFromProgID(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string szProgId,
|
||||
[Out]
|
||||
out Guid clsid);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[ComImport]
|
||||
[GuidAttribute("F31DFDE1-07B6-11d2-B2D8-0060083BA1FB")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOPCShutdown
|
||||
{
|
||||
void ShutdownRequest(
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
string szReason);
|
||||
}
|
||||
|
||||
/// <exclude />
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct CONNECTDATA
|
||||
{
|
||||
[MarshalAs(UnmanagedType.IUnknown)]
|
||||
object pUnk;
|
||||
[MarshalAs(UnmanagedType.I4)]
|
||||
int dwCookie;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,868 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
|
||||
public class Interop
|
||||
{
|
||||
public static PropertyID GetPropertyID(int input)
|
||||
{
|
||||
foreach (FieldInfo field in typeof(Property).GetFields(BindingFlags.Static | BindingFlags.Public))
|
||||
{
|
||||
PropertyID propertyId = (PropertyID)field.GetValue((object)typeof(PropertyID));
|
||||
if (input == propertyId.Code)
|
||||
return propertyId;
|
||||
}
|
||||
return new PropertyID(input);
|
||||
}
|
||||
|
||||
internal static BrowseElement GetBrowseElement(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
BrowseElement browseElement = (BrowseElement)null;
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
OPCBROWSEELEMENT structure = (OPCBROWSEELEMENT)Marshal.PtrToStructure(pInput, typeof(OPCBROWSEELEMENT));
|
||||
browseElement = new BrowseElement();
|
||||
browseElement.Name = structure.szName;
|
||||
browseElement.ItemPath = (string)null;
|
||||
browseElement.ItemName = structure.szItemID;
|
||||
browseElement.IsItem = (structure.dwFlagValue & 2) != 0;
|
||||
browseElement.HasChildren = (structure.dwFlagValue & 1) != 0;
|
||||
browseElement.Properties = Interop.GetItemProperties(ref structure.ItemProperties, deallocate);
|
||||
if (deallocate)
|
||||
Marshal.DestroyStructure(pInput, typeof(OPCBROWSEELEMENT));
|
||||
}
|
||||
return browseElement;
|
||||
}
|
||||
|
||||
internal static OPCBROWSEELEMENT GetBrowseElement(
|
||||
BrowseElement input,
|
||||
bool propertiesRequested)
|
||||
{
|
||||
OPCBROWSEELEMENT browseElement = new OPCBROWSEELEMENT();
|
||||
if (input != null)
|
||||
{
|
||||
browseElement.szName = input.Name;
|
||||
browseElement.szItemID = input.ItemName;
|
||||
browseElement.dwFlagValue = 0;
|
||||
browseElement.ItemProperties = Interop.GetItemProperties(input.Properties);
|
||||
if (input.IsItem)
|
||||
browseElement.dwFlagValue |= 2;
|
||||
if (input.HasChildren)
|
||||
browseElement.dwFlagValue |= 1;
|
||||
}
|
||||
return browseElement;
|
||||
}
|
||||
|
||||
internal static BrowseElement[] GetBrowseElements(
|
||||
ref IntPtr pInput,
|
||||
int count,
|
||||
bool deallocate)
|
||||
{
|
||||
BrowseElement[] browseElements = (BrowseElement[])null;
|
||||
if (pInput != IntPtr.Zero && count > 0)
|
||||
{
|
||||
browseElements = new BrowseElement[count];
|
||||
IntPtr pInput1 = pInput;
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
browseElements[index] = Interop.GetBrowseElement(pInput1, deallocate);
|
||||
pInput1 = (IntPtr)(pInput1.ToInt64() + (long)Marshal.SizeOf(typeof(OPCBROWSEELEMENT)));
|
||||
}
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInput);
|
||||
pInput = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
return browseElements;
|
||||
}
|
||||
|
||||
internal static IntPtr GetBrowseElements(BrowseElement[] input, bool propertiesRequested)
|
||||
{
|
||||
IntPtr browseElements = IntPtr.Zero;
|
||||
if (input != null && input.Length != 0)
|
||||
{
|
||||
browseElements = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCBROWSEELEMENT)) * input.Length);
|
||||
IntPtr ptr = browseElements;
|
||||
for (int index = 0; index < input.Length; ++index)
|
||||
{
|
||||
Marshal.StructureToPtr((object)Interop.GetBrowseElement(input[index], propertiesRequested), ptr, false);
|
||||
ptr = (IntPtr)(ptr.ToInt64() + (long)Marshal.SizeOf(typeof(OPCBROWSEELEMENT)));
|
||||
}
|
||||
}
|
||||
return browseElements;
|
||||
}
|
||||
internal static ItemProperty[] GetItemProperties(
|
||||
ref OPCITEMPROPERTIES input,
|
||||
bool deallocate)
|
||||
{
|
||||
ItemProperty[] itemProperties = (ItemProperty[])null;
|
||||
if (input.dwNumProperties > 0)
|
||||
{
|
||||
itemProperties = new ItemProperty[input.dwNumProperties];
|
||||
IntPtr pInput = input.pItemProperties;
|
||||
for (int index = 0; index < itemProperties.Length; ++index)
|
||||
{
|
||||
try
|
||||
{
|
||||
itemProperties[index] = Interop.GetItemProperty(pInput, deallocate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
itemProperties[index] = new ItemProperty();
|
||||
itemProperties[index].Description = ex.Message;
|
||||
itemProperties[index].ResultID = ResultID.E_FAIL;
|
||||
}
|
||||
pInput = (IntPtr)(pInput.ToInt64() + (long)Marshal.SizeOf(typeof(OPCITEMPROPERTY)));
|
||||
}
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(input.pItemProperties);
|
||||
input.pItemProperties = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
return itemProperties;
|
||||
}
|
||||
|
||||
internal static OPCITEMPROPERTIES GetItemProperties(ItemProperty[] input)
|
||||
{
|
||||
OPCITEMPROPERTIES itemProperties = new OPCITEMPROPERTIES();
|
||||
if (input != null && input.Length != 0)
|
||||
{
|
||||
itemProperties.hrErrorID = 0;
|
||||
itemProperties.dwReserved = 0;
|
||||
itemProperties.dwNumProperties = input.Length;
|
||||
itemProperties.pItemProperties = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMPROPERTY)) * input.Length);
|
||||
bool flag = false;
|
||||
IntPtr ptr = itemProperties.pItemProperties;
|
||||
for (int index = 0; index < input.Length; ++index)
|
||||
{
|
||||
Marshal.StructureToPtr((object)Interop.GetItemProperty(input[index]), ptr, false);
|
||||
ptr = (IntPtr)(ptr.ToInt64() + (long)Marshal.SizeOf(typeof(OPCITEMPROPERTY)));
|
||||
if (input[index].ResultID.Failed())
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
itemProperties.hrErrorID = 1;
|
||||
}
|
||||
return itemProperties;
|
||||
}
|
||||
|
||||
internal static ItemProperty GetItemProperty(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
ItemProperty itemProperty = (ItemProperty)null;
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
OPCITEMPROPERTY structure = (OPCITEMPROPERTY)Marshal.PtrToStructure(pInput, typeof(OPCITEMPROPERTY));
|
||||
itemProperty = new ItemProperty()
|
||||
{
|
||||
ID = Interop.GetPropertyID(structure.dwPropertyID),
|
||||
Description = structure.szDescription,
|
||||
DataType = Interop.GetType((VarEnum)structure.vtDataType),
|
||||
ItemPath = (string)null,
|
||||
ItemName = structure.szItemID
|
||||
};
|
||||
itemProperty.Value = Interop.UnmarshalPropertyValue(itemProperty.ID, structure.vValue);
|
||||
itemProperty.ResultID = Interop.GetResultID(structure.hrErrorID);
|
||||
if (structure.hrErrorID == -1073479674)
|
||||
itemProperty.ResultID = new ResultID(ResultID.Da.E_WRITEONLY, -1073479674L);
|
||||
if (deallocate)
|
||||
Marshal.DestroyStructure(pInput, typeof(OPCITEMPROPERTY));
|
||||
}
|
||||
return itemProperty;
|
||||
}
|
||||
internal static OPCITEMPROPERTY GetItemProperty(ItemProperty input)
|
||||
{
|
||||
OPCITEMPROPERTY itemProperty = new OPCITEMPROPERTY();
|
||||
if (input != null)
|
||||
{
|
||||
itemProperty.dwPropertyID = input.ID.Code;
|
||||
itemProperty.szDescription = input.Description;
|
||||
itemProperty.vtDataType = (short)Interop.GetType(input.DataType);
|
||||
itemProperty.vValue = Interop.MarshalPropertyValue(input.ID, input.Value);
|
||||
itemProperty.wReserved = (short)0;
|
||||
itemProperty.hrErrorID = Interop.GetResultID(input.ResultID);
|
||||
PropertyDescription propertyDescription = PropertyDescription.Find(input.ID);
|
||||
if (propertyDescription != null)
|
||||
itemProperty.vtDataType = (short)Interop.GetType(propertyDescription.Type);
|
||||
if (input.ResultID == ResultID.Da.E_WRITEONLY)
|
||||
itemProperty.hrErrorID = -1073479674;
|
||||
}
|
||||
return itemProperty;
|
||||
}
|
||||
|
||||
internal static int[] GetPropertyIDs(PropertyID[] propertyIDs)
|
||||
{
|
||||
ArrayList arrayList = new ArrayList();
|
||||
if (propertyIDs != null)
|
||||
{
|
||||
foreach (PropertyID propertyId in propertyIDs)
|
||||
arrayList.Add((object)propertyId.Code);
|
||||
}
|
||||
return (int[])arrayList.ToArray(typeof(int));
|
||||
}
|
||||
|
||||
internal static ResultID GetResultID(int input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case -2147467262:
|
||||
return new ResultID(ResultID.E_NOTSUPPORTED, (long)input);
|
||||
case -2147467259:
|
||||
return new ResultID(ResultID.E_FAIL, (long)input);
|
||||
case -2147352571:
|
||||
return new ResultID(ResultID.Da.E_BADTYPE, (long)input);
|
||||
case -2147352566:
|
||||
return new ResultID(ResultID.Da.E_RANGE, (long)input);
|
||||
case -2147217401:
|
||||
return new ResultID(ResultID.Hda.W_NOFILTER, (long)input);
|
||||
case -2147024882:
|
||||
return new ResultID(ResultID.E_OUTOFMEMORY, (long)input);
|
||||
case -2147024809:
|
||||
return new ResultID(ResultID.E_INVALIDARG, (long)input);
|
||||
case -1073479679:
|
||||
return new ResultID(ResultID.Da.E_INVALIDHANDLE, (long)input);
|
||||
case -1073479676:
|
||||
return new ResultID(ResultID.Da.E_BADTYPE, (long)input);
|
||||
case -1073479673:
|
||||
return new ResultID(ResultID.Da.E_UNKNOWN_ITEM_NAME, (long)input);
|
||||
case -1073479672:
|
||||
return new ResultID(ResultID.Da.E_INVALID_ITEM_NAME, (long)input);
|
||||
case -1073479671:
|
||||
return new ResultID(ResultID.Da.E_INVALID_FILTER, (long)input);
|
||||
case -1073479670:
|
||||
return new ResultID(ResultID.Da.E_UNKNOWN_ITEM_PATH, (long)input);
|
||||
case -1073479669:
|
||||
return new ResultID(ResultID.Da.E_RANGE, (long)input);
|
||||
case -1073479165:
|
||||
return new ResultID(ResultID.Da.E_INVALID_PID, (long)input);
|
||||
case -1073479164:
|
||||
return new ResultID(ResultID.Ae.E_INVALIDTIME, (long)input);
|
||||
case -1073479163:
|
||||
return new ResultID(ResultID.Ae.E_BUSY, (long)input);
|
||||
case -1073479162:
|
||||
return new ResultID(ResultID.Ae.E_NOINFO, (long)input);
|
||||
case -1073478655:
|
||||
return new ResultID(ResultID.Da.E_NO_ITEM_DEADBAND, (long)input);
|
||||
case -1073478654:
|
||||
return new ResultID(ResultID.Da.E_NO_ITEM_BUFFERING, (long)input);
|
||||
case -1073478653:
|
||||
return new ResultID(ResultID.Da.E_INVALIDCONTINUATIONPOINT, (long)input);
|
||||
case -1073478650:
|
||||
return new ResultID(ResultID.Da.E_NO_WRITEQT, (long)input);
|
||||
case -1073478649:
|
||||
return new ResultID(ResultID.Cpx.E_TYPE_CHANGED, (long)input);
|
||||
case -1073478648:
|
||||
return new ResultID(ResultID.Cpx.E_FILTER_DUPLICATE, (long)input);
|
||||
case -1073478647:
|
||||
return new ResultID(ResultID.Cpx.E_FILTER_INVALID, (long)input);
|
||||
case -1073478646:
|
||||
return new ResultID(ResultID.Cpx.E_FILTER_ERROR, (long)input);
|
||||
case -1073477888:
|
||||
return new ResultID(ResultID.Dx.E_PERSISTING, (long)input);
|
||||
case -1073477887:
|
||||
return new ResultID(ResultID.Dx.E_NOITEMLIST, (long)input);
|
||||
case -1073477886:
|
||||
return new ResultID(ResultID.Dx.E_VERSION_MISMATCH, (long)input);
|
||||
case -1073477885:
|
||||
return new ResultID(ResultID.Dx.E_VERSION_MISMATCH, (long)input);
|
||||
case -1073477884:
|
||||
return new ResultID(ResultID.Dx.E_UNKNOWN_ITEM_PATH, (long)input);
|
||||
case -1073477883:
|
||||
return new ResultID(ResultID.Dx.E_UNKNOWN_ITEM_NAME, (long)input);
|
||||
case -1073477882:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_ITEM_PATH, (long)input);
|
||||
case -1073477881:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_ITEM_NAME, (long)input);
|
||||
case -1073477880:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_NAME, (long)input);
|
||||
case -1073477879:
|
||||
return new ResultID(ResultID.Dx.E_DUPLICATE_NAME, (long)input);
|
||||
case -1073477878:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_BROWSE_PATH, (long)input);
|
||||
case -1073477877:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_SERVER_URL, (long)input);
|
||||
case -1073477876:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_SERVER_TYPE, (long)input);
|
||||
case -1073477875:
|
||||
return new ResultID(ResultID.Dx.E_UNSUPPORTED_SERVER_TYPE, (long)input);
|
||||
case -1073477874:
|
||||
return new ResultID(ResultID.Dx.E_CONNECTIONS_EXIST, (long)input);
|
||||
case -1073477873:
|
||||
return new ResultID(ResultID.Dx.E_TOO_MANY_CONNECTIONS, (long)input);
|
||||
case -1073477872:
|
||||
return new ResultID(ResultID.Dx.E_OVERRIDE_BADTYPE, (long)input);
|
||||
case -1073477871:
|
||||
return new ResultID(ResultID.Dx.E_OVERRIDE_RANGE, (long)input);
|
||||
case -1073477870:
|
||||
return new ResultID(ResultID.Dx.E_SUBSTITUTE_BADTYPE, (long)input);
|
||||
case -1073477869:
|
||||
return new ResultID(ResultID.Dx.E_SUBSTITUTE_RANGE, (long)input);
|
||||
case -1073477868:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_TARGET_ITEM, (long)input);
|
||||
case -1073477867:
|
||||
return new ResultID(ResultID.Dx.E_UNKNOWN_TARGET_ITEM, (long)input);
|
||||
case -1073477866:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_ALREADY_CONNECTED, (long)input);
|
||||
case -1073477865:
|
||||
return new ResultID(ResultID.Dx.E_UNKNOWN_SERVER_NAME, (long)input);
|
||||
case -1073477864:
|
||||
return new ResultID(ResultID.Dx.E_UNKNOWN_SOURCE_ITEM, (long)input);
|
||||
case -1073477863:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_SOURCE_ITEM, (long)input);
|
||||
case -1073477862:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_QUEUE_SIZE, (long)input);
|
||||
case -1073477861:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_DEADBAND, (long)input);
|
||||
case -1073477860:
|
||||
return new ResultID(ResultID.Dx.E_INVALID_CONFIG_FILE, (long)input);
|
||||
case -1073477859:
|
||||
return new ResultID(ResultID.Dx.E_PERSIST_FAILED, (long)input);
|
||||
case -1073477858:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_FAULT, (long)input);
|
||||
case -1073477857:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_NO_ACCESSS, (long)input);
|
||||
case -1073477856:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_FAULT, (long)input);
|
||||
case -1073477855:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_NO_ACCESSS, (long)input);
|
||||
case -1073477854:
|
||||
return new ResultID(ResultID.Dx.E_SUBSCRIPTION_FAULT, (long)input);
|
||||
case -1073477853:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BADRIGHTS, (long)input);
|
||||
case -1073477852:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BAD_QUALITY, (long)input);
|
||||
case -1073477851:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_BADTYPE, (long)input);
|
||||
case -1073477850:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_ITEM_RANGE, (long)input);
|
||||
case -1073477849:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_NOT_CONNECTED, (long)input);
|
||||
case -1073477848:
|
||||
return new ResultID(ResultID.Dx.E_SOURCE_SERVER_TIMEOUT, (long)input);
|
||||
case -1073477847:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_ITEM_DISCONNECTED, (long)input);
|
||||
case -1073477846:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_NO_WRITES_ATTEMPTED, (long)input);
|
||||
case -1073477845:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_ITEM_BADTYPE, (long)input);
|
||||
case -1073477844:
|
||||
return new ResultID(ResultID.Dx.E_TARGET_ITEM_RANGE, (long)input);
|
||||
case -1073475583:
|
||||
return new ResultID(ResultID.Hda.E_MAXEXCEEDED, (long)input);
|
||||
case -1073475580:
|
||||
return new ResultID(ResultID.Hda.E_INVALIDAGGREGATE, (long)input);
|
||||
case -1073475576:
|
||||
return new ResultID(ResultID.Hda.E_UNKNOWNATTRID, (long)input);
|
||||
case -1073475575:
|
||||
return new ResultID(ResultID.Hda.E_NOT_AVAIL, (long)input);
|
||||
case -1073475574:
|
||||
return new ResultID(ResultID.Hda.E_INVALIDDATATYPE, (long)input);
|
||||
case -1073475573:
|
||||
return new ResultID(ResultID.Hda.E_DATAEXISTS, (long)input);
|
||||
case -1073475572:
|
||||
return new ResultID(ResultID.Hda.E_INVALIDATTRID, (long)input);
|
||||
case -1073475571:
|
||||
return new ResultID(ResultID.Hda.E_NODATAEXISTS, (long)input);
|
||||
case 0:
|
||||
return new ResultID(ResultID.S_OK, (long)input);
|
||||
case 262157:
|
||||
return new ResultID(ResultID.Da.S_UNSUPPORTEDRATE, (long)input);
|
||||
case 262158:
|
||||
return new ResultID(ResultID.Da.S_CLAMP, (long)input);
|
||||
case 262656:
|
||||
return new ResultID(ResultID.Ae.S_ALREADYACKED, (long)input);
|
||||
case 262657:
|
||||
return new ResultID(ResultID.Ae.S_INVALIDBUFFERTIME, (long)input);
|
||||
case 262658:
|
||||
return new ResultID(ResultID.Ae.S_INVALIDMAXSIZE, (long)input);
|
||||
case 262659:
|
||||
return new ResultID(ResultID.Ae.S_INVALIDKEEPALIVETIME, (long)input);
|
||||
case 263172:
|
||||
return new ResultID(ResultID.Da.S_DATAQUEUEOVERFLOW, (long)input);
|
||||
case 263179:
|
||||
return new ResultID(ResultID.Cpx.S_FILTER_NO_DATA, (long)input);
|
||||
case 264064:
|
||||
return new ResultID(ResultID.Dx.S_TARGET_SUBSTITUTED, (long)input);
|
||||
case 264065:
|
||||
return new ResultID(ResultID.Dx.S_TARGET_OVERRIDEN, (long)input);
|
||||
case 264066:
|
||||
return new ResultID(ResultID.Dx.S_CLAMP, (long)input);
|
||||
case 1074008066:
|
||||
return new ResultID(ResultID.Hda.S_NODATA, (long)input);
|
||||
case 1074008067:
|
||||
return new ResultID(ResultID.Hda.S_MOREDATA, (long)input);
|
||||
case 1074008069:
|
||||
return new ResultID(ResultID.Hda.S_CURRENTVALUE, (long)input);
|
||||
case 1074008070:
|
||||
return new ResultID(ResultID.Hda.S_EXTRADATA, (long)input);
|
||||
case 1074008078:
|
||||
return new ResultID(ResultID.Hda.S_INSERTED, (long)input);
|
||||
case 1074008079:
|
||||
return new ResultID(ResultID.Hda.S_REPLACED, (long)input);
|
||||
default:
|
||||
if ((input & 2147418112) == 65536)
|
||||
return new ResultID(ResultID.E_NETWORK_ERROR, (long)input);
|
||||
return input >= 0 ? new ResultID(ResultID.S_FALSE, (long)input) : new ResultID(ResultID.E_FAIL, (long)input);
|
||||
}
|
||||
}
|
||||
internal static int GetResultID(ResultID input)
|
||||
{
|
||||
if (input.Name != (XmlQualifiedName)null && input.Name.Namespace == "http://opcfoundation.org/DataAccess/")
|
||||
{
|
||||
if (input == ResultID.S_OK)
|
||||
return 0;
|
||||
if (input == ResultID.E_FAIL)
|
||||
return -2147467259;
|
||||
if (input == ResultID.E_INVALIDARG)
|
||||
return -2147024809;
|
||||
if (input == ResultID.Da.E_BADTYPE)
|
||||
return -1073479676;
|
||||
if (input == ResultID.Da.E_READONLY || input == ResultID.Da.E_WRITEONLY)
|
||||
return -1073479674;
|
||||
if (input == ResultID.Da.E_RANGE)
|
||||
return -1073479669;
|
||||
if (input == ResultID.E_OUTOFMEMORY)
|
||||
return -2147024882;
|
||||
if (input == ResultID.E_NOTSUPPORTED)
|
||||
return -2147467262;
|
||||
if (input == ResultID.Da.E_INVALIDHANDLE)
|
||||
return -1073479679;
|
||||
if (input == ResultID.Da.E_UNKNOWN_ITEM_NAME)
|
||||
return -1073479673;
|
||||
if (input == ResultID.Da.E_INVALID_ITEM_NAME || input == ResultID.Da.E_INVALID_ITEM_PATH)
|
||||
return -1073479672;
|
||||
if (input == ResultID.Da.E_UNKNOWN_ITEM_PATH)
|
||||
return -1073479670;
|
||||
if (input == ResultID.Da.E_INVALID_FILTER)
|
||||
return -1073479671;
|
||||
if (input == ResultID.Da.S_UNSUPPORTEDRATE)
|
||||
return 262157;
|
||||
if (input == ResultID.Da.S_CLAMP)
|
||||
return 262158;
|
||||
if (input == ResultID.Da.E_INVALID_PID)
|
||||
return -1073479165;
|
||||
if (input == ResultID.Da.E_NO_ITEM_DEADBAND)
|
||||
return -1073478655;
|
||||
if (input == ResultID.Da.E_NO_ITEM_BUFFERING)
|
||||
return -1073478654;
|
||||
if (input == ResultID.Da.E_NO_WRITEQT)
|
||||
return -1073478650;
|
||||
if (input == ResultID.Da.E_INVALIDCONTINUATIONPOINT)
|
||||
return -1073478653;
|
||||
if (input == ResultID.Da.S_DATAQUEUEOVERFLOW)
|
||||
return 263172;
|
||||
}
|
||||
else if (input.Name != (XmlQualifiedName)null && input.Name.Namespace == "http://opcfoundation.org/ComplexData/")
|
||||
{
|
||||
if (input == ResultID.Cpx.E_TYPE_CHANGED)
|
||||
return -1073478649;
|
||||
if (input == ResultID.Cpx.E_FILTER_DUPLICATE)
|
||||
return -1073478648;
|
||||
if (input == ResultID.Cpx.E_FILTER_INVALID)
|
||||
return -1073478647;
|
||||
if (input == ResultID.Cpx.E_FILTER_ERROR)
|
||||
return -1073478646;
|
||||
if (input == ResultID.Cpx.S_FILTER_NO_DATA)
|
||||
return 263179;
|
||||
}
|
||||
else if (input.Name != (XmlQualifiedName)null && input.Name.Namespace == "http://opcfoundation.org/HistoricalDataAccess/")
|
||||
{
|
||||
if (input == ResultID.Hda.E_MAXEXCEEDED)
|
||||
return -1073475583;
|
||||
if (input == ResultID.Hda.S_NODATA)
|
||||
return 1074008066;
|
||||
if (input == ResultID.Hda.S_MOREDATA)
|
||||
return 1074008067;
|
||||
if (input == ResultID.Hda.E_INVALIDAGGREGATE)
|
||||
return -1073475580;
|
||||
if (input == ResultID.Hda.S_CURRENTVALUE)
|
||||
return 1074008069;
|
||||
if (input == ResultID.Hda.S_EXTRADATA)
|
||||
return 1074008070;
|
||||
if (input == ResultID.Hda.E_UNKNOWNATTRID)
|
||||
return -1073475576;
|
||||
if (input == ResultID.Hda.E_NOT_AVAIL)
|
||||
return -1073475575;
|
||||
if (input == ResultID.Hda.E_INVALIDDATATYPE)
|
||||
return -1073475574;
|
||||
if (input == ResultID.Hda.E_DATAEXISTS)
|
||||
return -1073475573;
|
||||
if (input == ResultID.Hda.E_INVALIDATTRID)
|
||||
return -1073475572;
|
||||
if (input == ResultID.Hda.E_NODATAEXISTS)
|
||||
return -1073475571;
|
||||
if (input == ResultID.Hda.S_INSERTED)
|
||||
return 1074008078;
|
||||
if (input == ResultID.Hda.S_REPLACED)
|
||||
return 1074008079;
|
||||
}
|
||||
if (input.Name != (XmlQualifiedName)null && input.Name.Namespace == "http://opcfoundation.org/DataExchange/")
|
||||
{
|
||||
if (input == ResultID.Dx.E_PERSISTING)
|
||||
return -1073477888;
|
||||
if (input == ResultID.Dx.E_NOITEMLIST)
|
||||
return -1073477887;
|
||||
if (input == ResultID.Dx.E_SERVER_STATE || input == ResultID.Dx.E_VERSION_MISMATCH)
|
||||
return -1073477885;
|
||||
if (input == ResultID.Dx.E_UNKNOWN_ITEM_PATH)
|
||||
return -1073477884;
|
||||
if (input == ResultID.Dx.E_UNKNOWN_ITEM_NAME)
|
||||
return -1073477883;
|
||||
if (input == ResultID.Dx.E_INVALID_ITEM_PATH)
|
||||
return -1073477882;
|
||||
if (input == ResultID.Dx.E_INVALID_ITEM_NAME)
|
||||
return -1073477881;
|
||||
if (input == ResultID.Dx.E_INVALID_NAME)
|
||||
return -1073477880;
|
||||
if (input == ResultID.Dx.E_DUPLICATE_NAME)
|
||||
return -1073477879;
|
||||
if (input == ResultID.Dx.E_INVALID_BROWSE_PATH)
|
||||
return -1073477878;
|
||||
if (input == ResultID.Dx.E_INVALID_SERVER_URL)
|
||||
return -1073477877;
|
||||
if (input == ResultID.Dx.E_INVALID_SERVER_TYPE)
|
||||
return -1073477876;
|
||||
if (input == ResultID.Dx.E_UNSUPPORTED_SERVER_TYPE)
|
||||
return -1073477875;
|
||||
if (input == ResultID.Dx.E_CONNECTIONS_EXIST)
|
||||
return -1073477874;
|
||||
if (input == ResultID.Dx.E_TOO_MANY_CONNECTIONS)
|
||||
return -1073477873;
|
||||
if (input == ResultID.Dx.E_OVERRIDE_BADTYPE)
|
||||
return -1073477872;
|
||||
if (input == ResultID.Dx.E_OVERRIDE_RANGE)
|
||||
return -1073477871;
|
||||
if (input == ResultID.Dx.E_SUBSTITUTE_BADTYPE)
|
||||
return -1073477870;
|
||||
if (input == ResultID.Dx.E_SUBSTITUTE_RANGE)
|
||||
return -1073477869;
|
||||
if (input == ResultID.Dx.E_INVALID_TARGET_ITEM)
|
||||
return -1073477868;
|
||||
if (input == ResultID.Dx.E_UNKNOWN_TARGET_ITEM)
|
||||
return -1073477867;
|
||||
if (input == ResultID.Dx.E_TARGET_ALREADY_CONNECTED)
|
||||
return -1073477866;
|
||||
if (input == ResultID.Dx.E_UNKNOWN_SERVER_NAME)
|
||||
return -1073477865;
|
||||
if (input == ResultID.Dx.E_UNKNOWN_SOURCE_ITEM)
|
||||
return -1073477864;
|
||||
if (input == ResultID.Dx.E_INVALID_SOURCE_ITEM)
|
||||
return -1073477863;
|
||||
if (input == ResultID.Dx.E_INVALID_QUEUE_SIZE)
|
||||
return -1073477862;
|
||||
if (input == ResultID.Dx.E_INVALID_DEADBAND)
|
||||
return -1073477861;
|
||||
if (input == ResultID.Dx.E_INVALID_CONFIG_FILE)
|
||||
return -1073477860;
|
||||
if (input == ResultID.Dx.E_PERSIST_FAILED)
|
||||
return -1073477859;
|
||||
if (input == ResultID.Dx.E_TARGET_FAULT)
|
||||
return -1073477858;
|
||||
if (input == ResultID.Dx.E_TARGET_NO_ACCESSS)
|
||||
return -1073477857;
|
||||
if (input == ResultID.Dx.E_SOURCE_SERVER_FAULT)
|
||||
return -1073477856;
|
||||
if (input == ResultID.Dx.E_SOURCE_SERVER_NO_ACCESSS)
|
||||
return -1073477855;
|
||||
if (input == ResultID.Dx.E_SUBSCRIPTION_FAULT)
|
||||
return -1073477854;
|
||||
if (input == ResultID.Dx.E_SOURCE_ITEM_BADRIGHTS)
|
||||
return -1073477853;
|
||||
if (input == ResultID.Dx.E_SOURCE_ITEM_BAD_QUALITY)
|
||||
return -1073477852;
|
||||
if (input == ResultID.Dx.E_SOURCE_ITEM_BADTYPE)
|
||||
return -1073477851;
|
||||
if (input == ResultID.Dx.E_SOURCE_ITEM_RANGE)
|
||||
return -1073477850;
|
||||
if (input == ResultID.Dx.E_SOURCE_SERVER_NOT_CONNECTED)
|
||||
return -1073477849;
|
||||
if (input == ResultID.Dx.E_SOURCE_SERVER_TIMEOUT)
|
||||
return -1073477848;
|
||||
if (input == ResultID.Dx.E_TARGET_ITEM_DISCONNECTED)
|
||||
return -1073477847;
|
||||
if (input == ResultID.Dx.E_TARGET_NO_WRITES_ATTEMPTED)
|
||||
return -1073477846;
|
||||
if (input == ResultID.Dx.E_TARGET_ITEM_BADTYPE)
|
||||
return -1073477845;
|
||||
if (input == ResultID.Dx.E_TARGET_ITEM_RANGE)
|
||||
return -1073477844;
|
||||
if (input == ResultID.Dx.S_TARGET_SUBSTITUTED)
|
||||
return 264064;
|
||||
if (input == ResultID.Dx.S_TARGET_OVERRIDEN)
|
||||
return 264065;
|
||||
if (input == ResultID.Dx.S_CLAMP)
|
||||
return 264066;
|
||||
}
|
||||
else if (input.Code == -1)
|
||||
return input.Succeeded() ? 1 : -2147467259;
|
||||
return input.Code;
|
||||
}
|
||||
|
||||
internal static VarEnum GetType(System.Type input)
|
||||
{
|
||||
if (input == (System.Type)null)
|
||||
return VarEnum.VT_EMPTY;
|
||||
if (input == typeof(sbyte))
|
||||
return VarEnum.VT_I1;
|
||||
if (input == typeof(byte))
|
||||
return VarEnum.VT_UI1;
|
||||
if (input == typeof(short))
|
||||
return VarEnum.VT_I2;
|
||||
if (input == typeof(ushort))
|
||||
return VarEnum.VT_UI2;
|
||||
if (input == typeof(int))
|
||||
return VarEnum.VT_I4;
|
||||
if (input == typeof(uint))
|
||||
return VarEnum.VT_UI4;
|
||||
if (input == typeof(long))
|
||||
return VarEnum.VT_I8;
|
||||
if (input == typeof(ulong))
|
||||
return VarEnum.VT_UI8;
|
||||
if (input == typeof(float))
|
||||
return VarEnum.VT_R4;
|
||||
if (input == typeof(double))
|
||||
return VarEnum.VT_R8;
|
||||
if (input == typeof(Decimal))
|
||||
return VarEnum.VT_CY;
|
||||
if (input == typeof(bool))
|
||||
return VarEnum.VT_BOOL;
|
||||
if (input == typeof(DateTime))
|
||||
return VarEnum.VT_DATE;
|
||||
if (input == typeof(string))
|
||||
return VarEnum.VT_BSTR;
|
||||
if (input == typeof(object))
|
||||
return VarEnum.VT_EMPTY;
|
||||
if (input == typeof(sbyte[]))
|
||||
return VarEnum.VT_I1 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(byte[]))
|
||||
return VarEnum.VT_UI1 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(short[]))
|
||||
return VarEnum.VT_I2 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(ushort[]))
|
||||
return VarEnum.VT_UI2 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(int[]))
|
||||
return VarEnum.VT_I4 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(uint[]))
|
||||
return VarEnum.VT_UI4 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(long[]))
|
||||
return VarEnum.VT_I8 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(ulong[]))
|
||||
return VarEnum.VT_UI8 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(float[]))
|
||||
return VarEnum.VT_R4 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(double[]))
|
||||
return VarEnum.VT_R8 | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(Decimal[]))
|
||||
return VarEnum.VT_CY | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(bool[]))
|
||||
return VarEnum.VT_BOOL | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(DateTime[]))
|
||||
return VarEnum.VT_DATE | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(string[]))
|
||||
return VarEnum.VT_BSTR | VarEnum.VT_ARRAY;
|
||||
if (input == typeof(object[]))
|
||||
return VarEnum.VT_VARIANT | VarEnum.VT_ARRAY;
|
||||
if (input == Type.ILLEGAL_TYPE)
|
||||
return (VarEnum)System.Enum.ToObject(typeof(VarEnum), (int)short.MaxValue);
|
||||
if (input == typeof(System.Type) || input == typeof(Quality))
|
||||
return VarEnum.VT_I2;
|
||||
return input == typeof(accessRights) || input == typeof(euType) ? VarEnum.VT_I4 : VarEnum.VT_EMPTY;
|
||||
}
|
||||
internal static System.Type GetType(VarEnum input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case VarEnum.VT_EMPTY:
|
||||
return (System.Type)null;
|
||||
case VarEnum.VT_I2:
|
||||
return typeof(short);
|
||||
case VarEnum.VT_I4:
|
||||
return typeof(int);
|
||||
case VarEnum.VT_R4:
|
||||
return typeof(float);
|
||||
case VarEnum.VT_R8:
|
||||
return typeof(double);
|
||||
case VarEnum.VT_CY:
|
||||
return typeof(Decimal);
|
||||
case VarEnum.VT_DATE:
|
||||
return typeof(DateTime);
|
||||
case VarEnum.VT_BSTR:
|
||||
return typeof(string);
|
||||
case VarEnum.VT_BOOL:
|
||||
return typeof(bool);
|
||||
case VarEnum.VT_I1:
|
||||
return typeof(sbyte);
|
||||
case VarEnum.VT_UI1:
|
||||
return typeof(byte);
|
||||
case VarEnum.VT_UI2:
|
||||
return typeof(ushort);
|
||||
case VarEnum.VT_UI4:
|
||||
return typeof(uint);
|
||||
case VarEnum.VT_I8:
|
||||
return typeof(long);
|
||||
case VarEnum.VT_UI8:
|
||||
return typeof(ulong);
|
||||
case VarEnum.VT_I2 | VarEnum.VT_ARRAY:
|
||||
return typeof(short[]);
|
||||
case VarEnum.VT_I4 | VarEnum.VT_ARRAY:
|
||||
return typeof(int[]);
|
||||
case VarEnum.VT_R4 | VarEnum.VT_ARRAY:
|
||||
return typeof(float[]);
|
||||
case VarEnum.VT_R8 | VarEnum.VT_ARRAY:
|
||||
return typeof(double[]);
|
||||
case VarEnum.VT_CY | VarEnum.VT_ARRAY:
|
||||
return typeof(Decimal[]);
|
||||
case VarEnum.VT_DATE | VarEnum.VT_ARRAY:
|
||||
return typeof(DateTime[]);
|
||||
case VarEnum.VT_BSTR | VarEnum.VT_ARRAY:
|
||||
return typeof(string[]);
|
||||
case VarEnum.VT_BOOL | VarEnum.VT_ARRAY:
|
||||
return typeof(bool[]);
|
||||
case VarEnum.VT_VARIANT | VarEnum.VT_ARRAY:
|
||||
return typeof(object[]);
|
||||
case VarEnum.VT_I1 | VarEnum.VT_ARRAY:
|
||||
return typeof(sbyte[]);
|
||||
case VarEnum.VT_UI1 | VarEnum.VT_ARRAY:
|
||||
return typeof(byte[]);
|
||||
case VarEnum.VT_UI2 | VarEnum.VT_ARRAY:
|
||||
return typeof(ushort[]);
|
||||
case VarEnum.VT_UI4 | VarEnum.VT_ARRAY:
|
||||
return typeof(uint[]);
|
||||
case VarEnum.VT_I8 | VarEnum.VT_ARRAY:
|
||||
return typeof(long[]);
|
||||
case VarEnum.VT_UI8 | VarEnum.VT_ARRAY:
|
||||
return typeof(ulong[]);
|
||||
default:
|
||||
return Type.ILLEGAL_TYPE;
|
||||
}
|
||||
}
|
||||
internal static object MarshalPropertyValue(PropertyID propertyID, object input)
|
||||
{
|
||||
if (input == null)
|
||||
return (object)null;
|
||||
try
|
||||
{
|
||||
if (propertyID == Property.DATATYPE)
|
||||
return (object)(short)Interop.GetType((System.Type)input);
|
||||
if (propertyID == Property.ACCESSRIGHTS)
|
||||
{
|
||||
switch ((accessRights)input)
|
||||
{
|
||||
case accessRights.readable:
|
||||
return (object)1;
|
||||
case accessRights.writable:
|
||||
return (object)2;
|
||||
case accessRights.readWritable:
|
||||
return (object)3;
|
||||
default:
|
||||
return (object)null;
|
||||
}
|
||||
}
|
||||
else if (propertyID == Property.EUTYPE)
|
||||
{
|
||||
switch ((euType)input)
|
||||
{
|
||||
case euType.noEnum:
|
||||
return (object)OPCEUTYPE.OPC_NOENUM;
|
||||
case euType.analog:
|
||||
return (object)OPCEUTYPE.OPC_ANALOG;
|
||||
case euType.enumerated:
|
||||
return (object)OPCEUTYPE.OPC_ENUMERATED;
|
||||
default:
|
||||
return (object)null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (propertyID == Property.QUALITY)
|
||||
return (object)((Quality)input).GetCode();
|
||||
if (propertyID == Property.TIMESTAMP)
|
||||
{
|
||||
if (input.GetType() == typeof(DateTime))
|
||||
{
|
||||
DateTime dateTime = (DateTime)input;
|
||||
return dateTime != DateTime.MinValue ? (object)dateTime.ToLocalTime() : (object)dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
internal static object UnmarshalPropertyValue(PropertyID propertyID, object input)
|
||||
{
|
||||
if (input == null)
|
||||
return (object)null;
|
||||
try
|
||||
{
|
||||
if (propertyID == Property.DATATYPE)
|
||||
return (object)Interop.GetType((VarEnum)System.Convert.ToUInt16(input));
|
||||
if (propertyID == Property.ACCESSRIGHTS)
|
||||
{
|
||||
switch (System.Convert.ToInt32(input))
|
||||
{
|
||||
case 1:
|
||||
return (object)accessRights.readable;
|
||||
case 2:
|
||||
return (object)accessRights.writable;
|
||||
case 3:
|
||||
return (object)accessRights.readWritable;
|
||||
default:
|
||||
return (object)null;
|
||||
}
|
||||
}
|
||||
else if (propertyID == Property.EUTYPE)
|
||||
{
|
||||
switch ((OPCEUTYPE)input)
|
||||
{
|
||||
case OPCEUTYPE.OPC_NOENUM:
|
||||
return (object)euType.noEnum;
|
||||
case OPCEUTYPE.OPC_ANALOG:
|
||||
return (object)euType.analog;
|
||||
case OPCEUTYPE.OPC_ENUMERATED:
|
||||
return (object)euType.enumerated;
|
||||
default:
|
||||
return (object)null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (propertyID == Property.QUALITY)
|
||||
return (object)new Quality(System.Convert.ToInt16(input));
|
||||
if (propertyID == Property.TIMESTAMP)
|
||||
{
|
||||
if (input.GetType() == typeof(DateTime))
|
||||
{
|
||||
DateTime dateTime = (DateTime)input;
|
||||
return dateTime != DateTime.MinValue ? (object)dateTime.ToLocalTime() : (object)dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
||||
@@ -1,961 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
|
||||
public enum accessRights
|
||||
{
|
||||
readable = 1,
|
||||
writable,
|
||||
readWritable
|
||||
}
|
||||
|
||||
public enum euType
|
||||
{
|
||||
noEnum = 1,
|
||||
analog,
|
||||
enumerated
|
||||
}
|
||||
|
||||
public enum limitBits
|
||||
{
|
||||
none,
|
||||
low,
|
||||
high,
|
||||
constant
|
||||
}
|
||||
|
||||
public enum qualityBits
|
||||
{
|
||||
good = 192,
|
||||
goodLocalOverride = 216,
|
||||
bad = 0,
|
||||
badConfigurationError = 4,
|
||||
badNotConnected = 8,
|
||||
badDeviceFailure = 12,
|
||||
badSensorFailure = 0x10,
|
||||
badLastKnownValue = 20,
|
||||
badCommFailure = 24,
|
||||
badOutOfService = 28,
|
||||
badWaitingForInitialData = 0x20,
|
||||
uncertain = 0x40,
|
||||
uncertainLastUsableValue = 68,
|
||||
uncertainSensorNotAccurate = 80,
|
||||
uncertainEUExceeded = 84,
|
||||
uncertainSubNormal = 88
|
||||
}
|
||||
|
||||
public interface IResult
|
||||
{
|
||||
string DiagnosticInfo { get; set; }
|
||||
ResultID ResultID { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct PropertyID : ISerializable
|
||||
{
|
||||
private int m_code;
|
||||
|
||||
private XmlQualifiedName m_name;
|
||||
|
||||
public PropertyID(XmlQualifiedName name)
|
||||
{
|
||||
m_name = name;
|
||||
m_code = 0;
|
||||
}
|
||||
|
||||
public PropertyID(int code)
|
||||
{
|
||||
m_name = null;
|
||||
m_code = code;
|
||||
}
|
||||
|
||||
public PropertyID(string name, int code, string ns)
|
||||
{
|
||||
m_name = new XmlQualifiedName(name, ns);
|
||||
m_code = code;
|
||||
}
|
||||
|
||||
private PropertyID(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
string name = "";
|
||||
string ns = "";
|
||||
enumerator.Reset();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (enumerator.Current.Name.Equals("NA"))
|
||||
{
|
||||
name = (string)enumerator.Current.Value;
|
||||
}
|
||||
else if (enumerator.Current.Name.Equals("NS"))
|
||||
{
|
||||
ns = (string)enumerator.Current.Value;
|
||||
}
|
||||
}
|
||||
|
||||
m_name = new XmlQualifiedName(name, ns);
|
||||
m_code = (int)info.GetValue("CO", typeof(int));
|
||||
}
|
||||
|
||||
public int Code => m_code;
|
||||
|
||||
public XmlQualifiedName Name => m_name;
|
||||
|
||||
public static bool operator !=(PropertyID a, PropertyID b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator ==(PropertyID a, PropertyID b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public override bool Equals(object target)
|
||||
{
|
||||
if (target != null && target.GetType() == typeof(PropertyID))
|
||||
{
|
||||
PropertyID propertyID = (PropertyID)target;
|
||||
if (propertyID.Code != 0 && Code != 0)
|
||||
{
|
||||
return propertyID.Code == Code;
|
||||
}
|
||||
|
||||
if (propertyID.Name != null && Name != null)
|
||||
{
|
||||
return propertyID.Name == Name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (Code != 0)
|
||||
{
|
||||
return Code.GetHashCode();
|
||||
}
|
||||
|
||||
if (Name != null)
|
||||
{
|
||||
return Name.GetHashCode();
|
||||
}
|
||||
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (m_name != null)
|
||||
{
|
||||
info.AddValue("NA", m_name.Name);
|
||||
info.AddValue("NS", m_name.Namespace);
|
||||
}
|
||||
|
||||
info.AddValue("CO", m_code);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Name != null && Code != 0)
|
||||
{
|
||||
return $"{Name.Name} ({Code})";
|
||||
}
|
||||
|
||||
if (Name != null)
|
||||
{
|
||||
return Name.Name;
|
||||
}
|
||||
|
||||
if (Code != 0)
|
||||
{
|
||||
return $"{Code}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private class Names
|
||||
{
|
||||
internal const string CODE = "CO";
|
||||
internal const string NAME = "NA";
|
||||
|
||||
internal const string NAMESPACE = "NS";
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct Quality
|
||||
{
|
||||
public static readonly Quality Bad = new Quality(qualityBits.bad);
|
||||
public static readonly Quality Good = new Quality(qualityBits.good);
|
||||
private limitBits m_limitBits;
|
||||
private qualityBits m_qualityBits;
|
||||
private byte m_vendorBits;
|
||||
public Quality(qualityBits quality)
|
||||
{
|
||||
m_qualityBits = quality;
|
||||
m_limitBits = limitBits.none;
|
||||
m_vendorBits = 0;
|
||||
}
|
||||
|
||||
public Quality(short code)
|
||||
{
|
||||
m_qualityBits = (qualityBits)(code & 0xFC);
|
||||
m_limitBits = (limitBits)(code & 3);
|
||||
m_vendorBits = (byte)((code & -253) >> 8);
|
||||
}
|
||||
|
||||
public limitBits LimitBits
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_limitBits;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_limitBits = value;
|
||||
}
|
||||
}
|
||||
|
||||
public qualityBits QualityBits
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_qualityBits;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_qualityBits = value;
|
||||
}
|
||||
}
|
||||
public byte VendorBits
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_vendorBits;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_vendorBits = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator !=(Quality a, Quality b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator ==(Quality a, Quality b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public override bool Equals(object target)
|
||||
{
|
||||
if (target == null || target.GetType() != typeof(Quality))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Quality quality = (Quality)target;
|
||||
if (QualityBits != quality.QualityBits)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LimitBits != quality.LimitBits)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VendorBits != quality.VendorBits)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public short GetCode()
|
||||
{
|
||||
ushort num = 0;
|
||||
num = (ushort)(num | (ushort)QualityBits);
|
||||
num = (ushort)(num | (ushort)LimitBits);
|
||||
num = (ushort)(num | (ushort)(VendorBits << 8));
|
||||
if (num > 32767)
|
||||
{
|
||||
return (short)(-(65536 - num));
|
||||
}
|
||||
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return GetCode();
|
||||
}
|
||||
|
||||
public void SetCode(short code)
|
||||
{
|
||||
m_qualityBits = (qualityBits)(code & 0xFC);
|
||||
m_limitBits = (limitBits)(code & 3);
|
||||
m_vendorBits = (byte)((code & -253) >> 8);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
string text = QualityBits.ToString();
|
||||
if (LimitBits != 0)
|
||||
{
|
||||
text += $"[{LimitBits.ToString()}]";
|
||||
}
|
||||
|
||||
if (VendorBits != 0)
|
||||
{
|
||||
text += string.Format(":{0,0:X}", VendorBits);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct ResultID : ISerializable
|
||||
{
|
||||
public static readonly ResultID E_ACCESS_DENIED = new ResultID("E_ACCESS_DENIED", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_FAIL = new ResultID("E_FAIL", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_INVALIDARG = new ResultID("E_INVALIDARG", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_NETWORK_ERROR = new ResultID("E_NETWORK_ERROR", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_NOTSUPPORTED = new ResultID("E_NOTSUPPORTED", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_OUTOFMEMORY = new ResultID("E_OUTOFMEMORY", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID E_TIMEDOUT = new ResultID("E_TIMEDOUT", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID S_FALSE = new ResultID("S_FALSE", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID S_OK = new ResultID("S_OK", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
private int m_code;
|
||||
|
||||
private XmlQualifiedName m_name;
|
||||
|
||||
public ResultID(XmlQualifiedName name)
|
||||
{
|
||||
m_name = name;
|
||||
m_code = -1;
|
||||
}
|
||||
|
||||
public ResultID(long code)
|
||||
{
|
||||
m_name = null;
|
||||
if (code > int.MaxValue)
|
||||
{
|
||||
code = -(4294967296L - code);
|
||||
}
|
||||
|
||||
m_code = (int)code;
|
||||
}
|
||||
|
||||
public ResultID(string name, string ns)
|
||||
{
|
||||
m_name = new XmlQualifiedName(name, ns);
|
||||
m_code = -1;
|
||||
}
|
||||
|
||||
public ResultID(ResultID resultID, long code)
|
||||
{
|
||||
m_name = resultID.Name;
|
||||
if (code > int.MaxValue)
|
||||
{
|
||||
code = -(4294967296L - code);
|
||||
}
|
||||
|
||||
m_code = (int)code;
|
||||
}
|
||||
|
||||
private ResultID(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
string name = (string)info.GetValue("NA", typeof(string));
|
||||
string ns = (string)info.GetValue("NS", typeof(string));
|
||||
m_name = new XmlQualifiedName(name, ns);
|
||||
m_code = (int)info.GetValue("CO", typeof(int));
|
||||
}
|
||||
|
||||
public int Code => m_code;
|
||||
|
||||
public XmlQualifiedName Name => m_name;
|
||||
|
||||
public static bool operator !=(ResultID a, ResultID b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator ==(ResultID a, ResultID b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public override bool Equals(object target)
|
||||
{
|
||||
if (target != null && target.GetType() == typeof(ResultID))
|
||||
{
|
||||
ResultID resultID = (ResultID)target;
|
||||
if (resultID.Code != -1 && Code != -1)
|
||||
{
|
||||
if (resultID.Code == Code)
|
||||
{
|
||||
return resultID.Name == Name;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resultID.Name != null && Name != null)
|
||||
{
|
||||
return resultID.Name == Name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Failed()
|
||||
{
|
||||
if (Code != -1)
|
||||
{
|
||||
return Code < 0;
|
||||
}
|
||||
|
||||
if (Name != null)
|
||||
{
|
||||
return Name.Name.StartsWith("E_");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (m_name != null)
|
||||
{
|
||||
info.AddValue("NA", m_name.Name);
|
||||
info.AddValue("NS", m_name.Namespace);
|
||||
}
|
||||
|
||||
info.AddValue("CO", m_code);
|
||||
}
|
||||
|
||||
public bool Succeeded()
|
||||
{
|
||||
if (Code != -1)
|
||||
{
|
||||
return Code >= 0;
|
||||
}
|
||||
|
||||
if (Name != null)
|
||||
{
|
||||
return Name.Name.StartsWith("S_");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Name != null)
|
||||
{
|
||||
return Name.Name;
|
||||
}
|
||||
|
||||
return string.Format("0x{0,0:X}", Code);
|
||||
}
|
||||
|
||||
public class Ae
|
||||
{
|
||||
public static readonly ResultID E_BUSY = new ResultID("E_BUSY", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
public static readonly ResultID E_INVALIDBRANCHNAME = new ResultID("E_INVALIDBRANCHNAME", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
public static readonly ResultID E_INVALIDTIME = new ResultID("E_INVALIDTIME", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
public static readonly ResultID E_NOINFO = new ResultID("E_NOINFO", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
public static readonly ResultID S_ALREADYACKED = new ResultID("S_ALREADYACKED", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
|
||||
public static readonly ResultID S_INVALIDBUFFERTIME = new ResultID("S_INVALIDBUFFERTIME", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
|
||||
public static readonly ResultID S_INVALIDKEEPALIVETIME = new ResultID("S_INVALIDKEEPALIVETIME", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
public static readonly ResultID S_INVALIDMAXSIZE = new ResultID("S_INVALIDMAXSIZE", "http://opcfoundation.org/AlarmAndEvents/");
|
||||
}
|
||||
|
||||
public class Cpx
|
||||
{
|
||||
public static readonly ResultID E_FILTER_DUPLICATE = new ResultID("E_FILTER_DUPLICATE", "http://opcfoundation.org/ComplexData/");
|
||||
public static readonly ResultID E_FILTER_ERROR = new ResultID("E_FILTER_ERROR", "http://opcfoundation.org/ComplexData/");
|
||||
public static readonly ResultID E_FILTER_INVALID = new ResultID("E_FILTER_INVALID", "http://opcfoundation.org/ComplexData/");
|
||||
public static readonly ResultID E_TYPE_CHANGED = new ResultID("E_TYPE_CHANGED", "http://opcfoundation.org/ComplexData/");
|
||||
public static readonly ResultID S_FILTER_NO_DATA = new ResultID("S_FILTER_NO_DATA", "http://opcfoundation.org/ComplexData/");
|
||||
}
|
||||
|
||||
public class Da
|
||||
{
|
||||
public static readonly ResultID E_BADTYPE = new ResultID("E_BADTYPE", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALID_FILTER = new ResultID("E_INVALID_FILTER", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALID_ITEM_NAME = new ResultID("E_INVALID_ITEM_NAME", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALID_ITEM_PATH = new ResultID("E_INVALID_ITEM_PATH", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALID_PID = new ResultID("E_INVALID_PID", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALIDCONTINUATIONPOINT = new ResultID("E_INVALIDCONTINUATIONPOINT", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_INVALIDHANDLE = new ResultID("E_INVALIDHANDLE", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_NO_ITEM_BUFFERING = new ResultID("E_NO_ITEM_BUFFERING", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_NO_ITEM_DEADBAND = new ResultID("E_NO_ITEM_DEADBAND", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_NO_ITEM_SAMPLING = new ResultID("E_NO_ITEM_SAMPLING", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_NO_WRITEQT = new ResultID("E_NO_WRITEQT", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_RANGE = new ResultID("E_RANGE", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_READONLY = new ResultID("E_READONLY", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_UNKNOWN_ITEM_NAME = new ResultID("E_UNKNOWN_ITEM_NAME", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_UNKNOWN_ITEM_PATH = new ResultID("E_UNKNOWN_ITEM_PATH", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID E_WRITEONLY = new ResultID("E_WRITEONLY", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID S_CLAMP = new ResultID("S_CLAMP", "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly ResultID S_DATAQUEUEOVERFLOW = new ResultID("S_DATAQUEUEOVERFLOW", "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly ResultID S_UNSUPPORTEDRATE = new ResultID("S_UNSUPPORTEDRATE", "http://opcfoundation.org/DataAccess/");
|
||||
}
|
||||
|
||||
public class Dx
|
||||
{
|
||||
public static readonly ResultID E_CONNECTIONS_EXIST = new ResultID("E_CONNECTIONS_EXIST", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_DUPLICATE_NAME = new ResultID("E_DUPLICATE_NAME", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_BROWSE_PATH = new ResultID("E_INVALID_BROWSE_PATH", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_CONFIG_FILE = new ResultID("E_INVALID_CONFIG_FILE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_DEADBAND = new ResultID("E_INVALID_DEADBAND", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_ITEM_NAME = new ResultID("E_INVALID_ITEM_NAME", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_ITEM_PATH = new ResultID("E_INVALID_ITEM_PATH", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_NAME = new ResultID("E_INVALID_NAME", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_QUEUE_SIZE = new ResultID("E_INVALID_QUEUE_SIZE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_SERVER_TYPE = new ResultID("E_INVALID_SERVER_TYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_SERVER_URL = new ResultID("E_INVALID_SERVER_URL", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_SOURCE_ITEM = new ResultID("E_INVALID_SOURCE_ITEM", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_INVALID_TARGET_ITEM = new ResultID("E_INVALID_TARGET_ITEM", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_NOITEMLIST = new ResultID("E_NOITEMLIST", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_OVERRIDE_BADTYPE = new ResultID("E_OVERRIDE_BADTYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_OVERRIDE_RANGE = new ResultID("E_OVERRIDE_RANGE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_PERSIST_FAILED = new ResultID("E_PERSIST_FAILED", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_PERSISTING = new ResultID("E_PERSISTING", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SERVER_STATE = new ResultID("E_SERVER_STATE", "http://opcfoundation.org/DataExchange/");
|
||||
|
||||
public static readonly ResultID E_SOURCE_ITEM_BAD_QUALITY = new ResultID("E_SOURCE_ITEM_BAD_QUALITY", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_ITEM_BADRIGHTS = new ResultID("E_SOURCE_ITEM_BADRIGHTS", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_ITEM_BADTYPE = new ResultID("E_SOURCE_ITEM_BADTYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_ITEM_RANGE = new ResultID("E_SOURCE_ITEM_RANGE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_SERVER_FAULT = new ResultID("E_SOURCE_SERVER_FAULT", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_SERVER_NO_ACCESSS = new ResultID("E_SOURCE_SERVER_NO_ACCESSS", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_SERVER_NOT_CONNECTED = new ResultID("E_SOURCE_SERVER_NOT_CONNECTED", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SOURCE_SERVER_TIMEOUT = new ResultID("E_SOURCE_SERVER_TIMEOUT", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SUBSCRIPTION_FAULT = new ResultID("E_SUBSCRIPTION_FAULT", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SUBSTITUTE_BADTYPE = new ResultID("E_SUBSTITUTE_BADTYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_SUBSTITUTE_RANGE = new ResultID("E_SUBSTITUTE_RANGE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_ALREADY_CONNECTED = new ResultID("E_TARGET_ALREADY_CONNECTED", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_FAULT = new ResultID("E_TARGET_FAULT", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_ITEM_BADTYPE = new ResultID("E_TARGET_ITEM_BADTYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_ITEM_DISCONNECTED = new ResultID("E_TARGET_ITEM_DISCONNECTED", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_ITEM_RANGE = new ResultID("E_TARGET_ITEM_RANGE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_NO_ACCESSS = new ResultID("E_TARGET_NO_ACCESSS", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TARGET_NO_WRITES_ATTEMPTED = new ResultID("E_TARGET_NO_WRITES_ATTEMPTED", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_TOO_MANY_CONNECTIONS = new ResultID("E_TOO_MANY_CONNECTIONS", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNKNOWN_ITEM_NAME = new ResultID("E_UNKNOWN_ITEM_NAME", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNKNOWN_ITEM_PATH = new ResultID("E_UNKNOWN_ITEM_PATH", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNKNOWN_SERVER_NAME = new ResultID("E_UNKNOWN_SERVER_NAME", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNKNOWN_SOURCE_ITEM = new ResultID("E_UNKNOWN_SOURCE_ITEM", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNKNOWN_TARGET_ITEM = new ResultID("E_UNKNOWN_TARGET_ITEM", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_UNSUPPORTED_SERVER_TYPE = new ResultID("E_UNSUPPORTED_SERVER_TYPE", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID E_VERSION_MISMATCH = new ResultID("E_VERSION_MISMATCH", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID S_CLAMP = new ResultID("S_CLAMP", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID S_TARGET_OVERRIDEN = new ResultID("S_TARGET_OVERRIDEN", "http://opcfoundation.org/DataExchange/");
|
||||
public static readonly ResultID S_TARGET_SUBSTITUTED = new ResultID("S_TARGET_SUBSTITUTED", "http://opcfoundation.org/DataExchange/");
|
||||
}
|
||||
|
||||
public class Hda
|
||||
{
|
||||
public static readonly ResultID E_DATAEXISTS = new ResultID("E_DATAEXISTS", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_INVALIDAGGREGATE = new ResultID("E_INVALIDAGGREGATE", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_INVALIDATTRID = new ResultID("E_INVALIDATTRID", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_INVALIDDATATYPE = new ResultID("E_INVALIDDATATYPE", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_MAXEXCEEDED = new ResultID("E_MAXEXCEEDED", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
|
||||
public static readonly ResultID E_NODATAEXISTS = new ResultID("E_NODATAEXISTS", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_NOT_AVAIL = new ResultID("E_NOT_AVAIL", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID E_UNKNOWNATTRID = new ResultID("E_UNKNOWNATTRID", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_CURRENTVALUE = new ResultID("S_CURRENTVALUE", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_EXTRADATA = new ResultID("S_EXTRADATA", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_INSERTED = new ResultID("S_INSERTED", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_MOREDATA = new ResultID("S_MOREDATA", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_NODATA = new ResultID("S_NODATA", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID S_REPLACED = new ResultID("S_REPLACED", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
public static readonly ResultID W_NOFILTER = new ResultID("W_NOFILTER", "http://opcfoundation.org/HistoricalDataAccess/");
|
||||
}
|
||||
|
||||
private class Names
|
||||
{
|
||||
internal const string CODE = "CO";
|
||||
internal const string NAME = "NA";
|
||||
|
||||
internal const string NAMESPACE = "NS";
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class ItemProperty : ICloneable, IResult
|
||||
{
|
||||
private System.Type m_datatype;
|
||||
private string m_description;
|
||||
private string m_diagnosticInfo;
|
||||
private PropertyID m_id;
|
||||
private string m_itemName;
|
||||
private string m_itemPath;
|
||||
private ResultID m_resultID = ResultID.S_OK;
|
||||
private object m_value;
|
||||
public System.Type DataType
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_datatype;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_datatype = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_description = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string DiagnosticInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_diagnosticInfo;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_diagnosticInfo = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyID ID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_id = value;
|
||||
}
|
||||
}
|
||||
public string ItemName
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_itemName;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_itemName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ItemPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_itemPath;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_itemPath = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ResultID ResultID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_resultID;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_resultID = value;
|
||||
}
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object Clone()
|
||||
{
|
||||
ItemProperty obj = (ItemProperty)MemberwiseClone();
|
||||
|
||||
obj.Value = Comn.Convert.Clone(Value);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
public class Property
|
||||
{
|
||||
public static readonly PropertyID ACCESSRIGHTS = new PropertyID("accessRights", 5, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID ALARM_AREA_LIST = new PropertyID("alarmAreaList", 302, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID ALARM_QUICK_HELP = new PropertyID("alarmQuickHelp", 301, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID CLOSELABEL = new PropertyID("closeLabel", 106, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID CONDITION_LOGIC = new PropertyID("conditionLogic", 304, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID CONDITION_STATUS = new PropertyID("conditionStatus", 300, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID CONSISTENCY_WINDOW = new PropertyID("consistencyWindow", 605, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DATA_FILTER_VALUE = new PropertyID("dataFilterValue", 609, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DATATYPE = new PropertyID("dataType", 1, "http://opcfoundation.org/DataAccess/");
|
||||
|
||||
public static readonly PropertyID DEADBAND = new PropertyID("deadband", 306, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DESCRIPTION = new PropertyID("description", 101, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DEVIATION_LIMIT = new PropertyID("deviationLimit", 312, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DICTIONARY = new PropertyID("dictionary", 603, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID DICTIONARY_ID = new PropertyID("dictionaryID", 601, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID ENGINEERINGUINTS = new PropertyID("engineeringUnits", 100, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID EUINFO = new PropertyID("euInfo", 8, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID EUTYPE = new PropertyID("euType", 7, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID HI_LIMIT = new PropertyID("hiLimit", 308, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID HIGHEU = new PropertyID("highEU", 102, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID HIGHIR = new PropertyID("highIR", 104, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID HIHI_LIMIT = new PropertyID("hihiLimit", 307, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID LIMIT_EXCEEDED = new PropertyID("limitExceeded", 305, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID LO_LIMIT = new PropertyID("loLimit", 309, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID LOLO_LIMIT = new PropertyID("loloLimit", 310, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID LOWEU = new PropertyID("lowEU", 103, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID LOWIR = new PropertyID("lowIR", 105, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID MAXIMUM_VALUE = new PropertyID("maximumValue", 110, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID MINIMUM_VALUE = new PropertyID("minimumValue", 109, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID OPENLABEL = new PropertyID("openLabel", 107, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID PRIMARY_ALARM_AREA = new PropertyID("primaryAlarmArea", 303, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID QUALITY = new PropertyID("quality", 3, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID RATE_CHANGE_LIMIT = new PropertyID("rangeOfChangeLimit", 311, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID SCANRATE = new PropertyID("scanRate", 6, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID SOUNDFILE = new PropertyID("soundFile", 313, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID TIMESTAMP = new PropertyID("timestamp", 4, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID TIMEZONE = new PropertyID("timeZone", 108, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID TYPE_DESCRIPTION = new PropertyID("typeDescription", 604, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID TYPE_ID = new PropertyID("typeID", 602, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID TYPE_SYSTEM_ID = new PropertyID("typeSystemID", 600, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID UNCONVERTED_ITEM_ID = new PropertyID("unconvertedItemID", 607, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID UNFILTERED_ITEM_ID = new PropertyID("unfilteredItemID", 608, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID VALUE = new PropertyID("value", 2, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID VALUE_PRECISION = new PropertyID("valuePrecision", 111, "http://opcfoundation.org/DataAccess/");
|
||||
public static readonly PropertyID WRITE_BEHAVIOR = new PropertyID("writeBehavior", 606, "http://opcfoundation.org/DataAccess/");
|
||||
}
|
||||
public class Type
|
||||
{
|
||||
public static System.Type ANY_TYPE = typeof(object);
|
||||
public static System.Type ARRAY_ANY_TYPE = typeof(object[]);
|
||||
public static System.Type ARRAY_BOOLEAN = typeof(bool[]);
|
||||
public static System.Type ARRAY_DATETIME = typeof(DateTime[]);
|
||||
public static System.Type ARRAY_DECIMAL = typeof(decimal[]);
|
||||
public static System.Type ARRAY_DOUBLE = typeof(double[]);
|
||||
public static System.Type ARRAY_FLOAT = typeof(float[]);
|
||||
public static System.Type ARRAY_INT = typeof(int[]);
|
||||
public static System.Type ARRAY_LONG = typeof(long[]);
|
||||
public static System.Type ARRAY_SHORT = typeof(short[]);
|
||||
public static System.Type ARRAY_STRING = typeof(string[]);
|
||||
public static System.Type ARRAY_UINT = typeof(uint[]);
|
||||
public static System.Type ARRAY_ULONG = typeof(ulong[]);
|
||||
public static System.Type ARRAY_USHORT = typeof(ushort[]);
|
||||
public static System.Type BINARY = typeof(byte[]);
|
||||
public static System.Type BOOLEAN = typeof(bool);
|
||||
public static System.Type BYTE = typeof(byte);
|
||||
public static System.Type DATETIME = typeof(DateTime);
|
||||
public static System.Type DECIMAL = typeof(decimal);
|
||||
public static System.Type DOUBLE = typeof(double);
|
||||
public static System.Type DURATION = typeof(TimeSpan);
|
||||
public static System.Type FLOAT = typeof(float);
|
||||
public static System.Type ILLEGAL_TYPE = typeof(Type);
|
||||
public static System.Type INT = typeof(int);
|
||||
public static System.Type LONG = typeof(long);
|
||||
public static System.Type SBYTE = typeof(sbyte);
|
||||
public static System.Type SHORT = typeof(short);
|
||||
|
||||
public static System.Type STRING = typeof(string);
|
||||
public static System.Type UINT = typeof(uint);
|
||||
public static System.Type ULONG = typeof(ulong);
|
||||
public static System.Type USHORT = typeof(ushort);
|
||||
public static System.Type[] Enumerate()
|
||||
{
|
||||
ArrayList arrayList = new ArrayList();
|
||||
FieldInfo[] fields = typeof(Type).GetFields(BindingFlags.Static | BindingFlags.Public);
|
||||
foreach (FieldInfo fieldInfo in fields)
|
||||
{
|
||||
arrayList.Add(fieldInfo.GetValue(typeof(System.Type)));
|
||||
}
|
||||
|
||||
return (System.Type[])arrayList.ToArray(typeof(System.Type));
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class PropertyDescription
|
||||
{
|
||||
public static readonly PropertyDescription ACCESSRIGHTS = new PropertyDescription(Property.ACCESSRIGHTS, typeof(accessRights), "Item Access Rights");
|
||||
public static readonly PropertyDescription ALARM_AREA_LIST = new PropertyDescription(Property.ALARM_AREA_LIST, typeof(string), "Alarm Area List");
|
||||
public static readonly PropertyDescription ALARM_QUICK_HELP = new PropertyDescription(Property.ALARM_QUICK_HELP, typeof(string), "Alarm Quick Help");
|
||||
public static readonly PropertyDescription CLOSELABEL = new PropertyDescription(Property.CLOSELABEL, typeof(string), "Contact Close Label");
|
||||
public static readonly PropertyDescription CONDITION_LOGIC = new PropertyDescription(Property.CONDITION_LOGIC, typeof(string), "Condition Logic");
|
||||
public static readonly PropertyDescription CONDITION_STATUS = new PropertyDescription(Property.CONDITION_STATUS, typeof(string), "Condition Status");
|
||||
public static readonly PropertyDescription CONSISTENCY_WINDOW = new PropertyDescription(Property.CONSISTENCY_WINDOW, typeof(string), "Consistency Window");
|
||||
public static readonly PropertyDescription DATA_FILTER_VALUE = new PropertyDescription(Property.DATA_FILTER_VALUE, typeof(string), "Data Filter Value");
|
||||
public static readonly PropertyDescription DATATYPE = new PropertyDescription(Property.DATATYPE, typeof(System.Type), "Item Canonical DataType");
|
||||
public static readonly PropertyDescription DEADBAND = new PropertyDescription(Property.DEADBAND, typeof(double), "Deadband");
|
||||
public static readonly PropertyDescription DESCRIPTION = new PropertyDescription(Property.DESCRIPTION, typeof(string), "Item Description");
|
||||
public static readonly PropertyDescription DEVIATION_LIMIT = new PropertyDescription(Property.DEVIATION_LIMIT, typeof(double), "Deviation Limit");
|
||||
public static readonly PropertyDescription DICTIONARY = new PropertyDescription(Property.DICTIONARY, typeof(object), "Dictionary");
|
||||
public static readonly PropertyDescription DICTIONARY_ID = new PropertyDescription(Property.DICTIONARY_ID, typeof(string), "Dictionary ID");
|
||||
public static readonly PropertyDescription ENGINEERINGUINTS = new PropertyDescription(Property.ENGINEERINGUINTS, typeof(string), "EU Units");
|
||||
public static readonly PropertyDescription EUINFO = new PropertyDescription(Property.EUINFO, typeof(string[]), "Item EU Info");
|
||||
public static readonly PropertyDescription EUTYPE = new PropertyDescription(Property.EUTYPE, typeof(euType), "Item EU Type");
|
||||
public static readonly PropertyDescription HI_LIMIT = new PropertyDescription(Property.HI_LIMIT, typeof(double), "Hi Limit");
|
||||
public static readonly PropertyDescription HIGHEU = new PropertyDescription(Property.HIGHEU, typeof(double), "High EU");
|
||||
public static readonly PropertyDescription HIGHIR = new PropertyDescription(Property.HIGHIR, typeof(double), "High Instrument Range");
|
||||
public static readonly PropertyDescription HIHI_LIMIT = new PropertyDescription(Property.HIHI_LIMIT, typeof(double), "HiHi Limit");
|
||||
public static readonly PropertyDescription LIMIT_EXCEEDED = new PropertyDescription(Property.LIMIT_EXCEEDED, typeof(string), "Limit Exceeded");
|
||||
public static readonly PropertyDescription LO_LIMIT = new PropertyDescription(Property.LO_LIMIT, typeof(double), "Lo Limit");
|
||||
public static readonly PropertyDescription LOLO_LIMIT = new PropertyDescription(Property.LOLO_LIMIT, typeof(double), "LoLo Limit");
|
||||
public static readonly PropertyDescription LOWEU = new PropertyDescription(Property.LOWEU, typeof(double), "Low EU");
|
||||
public static readonly PropertyDescription LOWIR = new PropertyDescription(Property.LOWIR, typeof(double), "Low Instrument Range");
|
||||
public static readonly PropertyDescription MAXIMUM_VALUE = new PropertyDescription(Property.MAXIMUM_VALUE, typeof(object), "Maximum Value");
|
||||
public static readonly PropertyDescription MINIMUM_VALUE = new PropertyDescription(Property.MINIMUM_VALUE, typeof(object), "Minimum Value");
|
||||
public static readonly PropertyDescription OPENLABEL = new PropertyDescription(Property.OPENLABEL, typeof(string), "Contact Open Label");
|
||||
public static readonly PropertyDescription PRIMARY_ALARM_AREA = new PropertyDescription(Property.PRIMARY_ALARM_AREA, typeof(string), "Primary Alarm Area");
|
||||
public static readonly PropertyDescription QUALITY = new PropertyDescription(Property.QUALITY, typeof(Quality), "Item Quality");
|
||||
public static readonly PropertyDescription RATE_CHANGE_LIMIT = new PropertyDescription(Property.RATE_CHANGE_LIMIT, typeof(double), "Rate of Change Limit");
|
||||
public static readonly PropertyDescription SCANRATE = new PropertyDescription(Property.SCANRATE, typeof(float), "Server Scan Rate");
|
||||
public static readonly PropertyDescription SOUNDFILE = new PropertyDescription(Property.SOUNDFILE, typeof(string), "Sound File");
|
||||
public static readonly PropertyDescription TIMESTAMP = new PropertyDescription(Property.TIMESTAMP, typeof(DateTime), "Item Timestamp");
|
||||
public static readonly PropertyDescription TIMEZONE = new PropertyDescription(Property.TIMEZONE, typeof(int), "Timezone");
|
||||
public static readonly PropertyDescription TYPE_DESCRIPTION = new PropertyDescription(Property.TYPE_DESCRIPTION, typeof(string), "Type Description");
|
||||
public static readonly PropertyDescription TYPE_ID = new PropertyDescription(Property.TYPE_ID, typeof(string), "Type ID");
|
||||
public static readonly PropertyDescription TYPE_SYSTEM_ID = new PropertyDescription(Property.TYPE_SYSTEM_ID, typeof(string), "Type System ID");
|
||||
public static readonly PropertyDescription UNCONVERTED_ITEM_ID = new PropertyDescription(Property.UNCONVERTED_ITEM_ID, typeof(string), "Unconverted Item ID");
|
||||
public static readonly PropertyDescription UNFILTERED_ITEM_ID = new PropertyDescription(Property.UNFILTERED_ITEM_ID, typeof(string), "Unfiltered Item ID");
|
||||
public static readonly PropertyDescription VALUE = new PropertyDescription(Property.VALUE, typeof(object), "Item Value");
|
||||
public static readonly PropertyDescription VALUE_PRECISION = new PropertyDescription(Property.VALUE_PRECISION, typeof(object), "Value Precision");
|
||||
public static readonly PropertyDescription WRITE_BEHAVIOR = new PropertyDescription(Property.WRITE_BEHAVIOR, typeof(string), "Write Behavior");
|
||||
private PropertyID m_id;
|
||||
|
||||
private string m_name;
|
||||
private System.Type m_type;
|
||||
public PropertyDescription(PropertyID id, System.Type type, string name)
|
||||
{
|
||||
ID = id;
|
||||
Type = type;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public PropertyID ID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_id = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Type Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_type = value;
|
||||
}
|
||||
}
|
||||
public static PropertyDescription[] Enumerate()
|
||||
{
|
||||
ArrayList arrayList = new ArrayList();
|
||||
FieldInfo[] fields = typeof(PropertyDescription).GetFields(BindingFlags.Static | BindingFlags.Public);
|
||||
foreach (FieldInfo fieldInfo in fields)
|
||||
{
|
||||
arrayList.Add(fieldInfo.GetValue(typeof(PropertyDescription)));
|
||||
}
|
||||
|
||||
return (PropertyDescription[])arrayList.ToArray(typeof(PropertyDescription));
|
||||
}
|
||||
|
||||
public static PropertyDescription Find(PropertyID id)
|
||||
{
|
||||
FieldInfo[] fields = typeof(PropertyDescription).GetFields(BindingFlags.Static | BindingFlags.Public);
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
PropertyDescription propertyDescription = (PropertyDescription)fields[i].GetValue(typeof(PropertyDescription));
|
||||
if (propertyDescription.ID == id)
|
||||
{
|
||||
return propertyDescription;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA;
|
||||
|
||||
internal static class CollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除符合条件的元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="where"></param>
|
||||
internal static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
|
||||
{
|
||||
foreach (var obj in @this.Where(where).ToList())
|
||||
{
|
||||
@this.Remove(obj);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 将项目列表分解为特定大小的块
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="chunksize"></param>
|
||||
/// <returns></returns>
|
||||
internal static List<List<T>> ChunkTrivialBetter<T>(this IEnumerable<T> source, int chunksize)
|
||||
{
|
||||
var pos = 0;
|
||||
List<List<T>> n = new();
|
||||
while (source.Skip(pos).Any())
|
||||
{
|
||||
n.Add(source.Skip(pos).Take(chunksize).ToList());
|
||||
pos += chunksize;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// API首页:http://rrqm_home.gitee.io/touchsocket/
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA;
|
||||
|
||||
/// <summary>
|
||||
/// DictionaryExtension
|
||||
/// </summary>
|
||||
internal static class DictionaryExtension
|
||||
{
|
||||
#region 字典扩展
|
||||
|
||||
/// <summary>
|
||||
/// 移除满足条件的项目。
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="pairs"></param>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
internal static int RemoveWhen<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> pairs, Func<KeyValuePair<TKey, TValue>, bool> func)
|
||||
{
|
||||
var list = new List<TKey>();
|
||||
foreach (var item in pairs)
|
||||
{
|
||||
if (func?.Invoke(item) == true)
|
||||
{
|
||||
list.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (pairs.TryRemove(item, out _))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#if NET45_OR_GREATER || NETSTANDARD2_0_OR_GREATER
|
||||
|
||||
/// <summary>
|
||||
/// 尝试添加
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool TryAdd<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey, TValue value)
|
||||
{
|
||||
if (dictionary.ContainsKey(tkey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
dictionary.Add(tkey, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 尝试添加
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
internal static void AddOrUpdate<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey, TValue value)
|
||||
{
|
||||
if (dictionary.ContainsKey(tkey))
|
||||
{
|
||||
dictionary[tkey] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(tkey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取值。如果键不存在,则返回默认值。
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <returns></returns>
|
||||
internal static TValue GetValue<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey)
|
||||
{
|
||||
return dictionary.TryGetValue(tkey, out var value) ? value : default;
|
||||
}
|
||||
#endregion 字典扩展
|
||||
}
|
||||
@@ -1,457 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Da;
|
||||
using ThingsGateway.Foundation.Adapter.OPCDA.Rcw;
|
||||
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
//部分非托管交互代码来自https://gitee.com/Zer0Day/opc-client与OPC基金会opcnet库,更改部分逻辑
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA;
|
||||
/// <summary>
|
||||
/// 订阅变化项
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
public delegate void DataChangedEventHandler(List<ItemReadResult> values);
|
||||
/// <summary>
|
||||
/// OPCDAClient
|
||||
/// </summary>
|
||||
public class OPCDAClient : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// LogAction
|
||||
/// </summary>
|
||||
private readonly Action<byte, object, string, Exception> _logAction;
|
||||
|
||||
private readonly object checkLock = new();
|
||||
|
||||
private Timer checkTimer;
|
||||
|
||||
private int IsExit = 1;
|
||||
/// <summary>
|
||||
/// 当前保存的需订阅列表
|
||||
/// </summary>
|
||||
private Dictionary<string, List<OpcItem>> ItemDicts = new();
|
||||
|
||||
private OpcServer m_server;
|
||||
private bool publicConnect;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public OPCDAClient(Action<byte, object, string, Exception> logAction)
|
||||
{
|
||||
#if (NET6_0_OR_GREATER)
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
throw new NotSupportedException("不支持非windows系统");
|
||||
}
|
||||
#endif
|
||||
_logAction = logAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据变化事件
|
||||
/// </summary>
|
||||
public event DataChangedEventHandler DataChangedHandler;
|
||||
|
||||
/// <summary>
|
||||
/// 是否连接成功
|
||||
/// </summary>
|
||||
public bool IsConnected => m_server?.IsConnected == true;
|
||||
|
||||
/// <summary>
|
||||
/// 当前配置
|
||||
/// </summary>
|
||||
public OPCNode OPCNode { get; private set; }
|
||||
private List<OpcGroup> Groups => m_server.OpcGroups;
|
||||
|
||||
/// <summary>
|
||||
/// 添加节点,需要在连接成功后执行
|
||||
/// </summary>
|
||||
/// <param name="items">组名称/变量节点,注意每次添加的组名称不能相同</param>
|
||||
public void AddItems(Dictionary<string, List<OpcItem>> items)
|
||||
{
|
||||
if (IsExit == 1) throw new("对象已释放");
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (IsExit == 1) throw new("对象已释放");
|
||||
try
|
||||
{
|
||||
var subscription = m_server.AddGroup(item.Key, true, OPCNode.UpdateRate, OPCNode.DeadBand);
|
||||
subscription.ActiveSubscribe = OPCNode.ActiveSubscribe;
|
||||
subscription.OnDataChanged += Subscription_OnDataChanged;
|
||||
subscription.OnReadCompleted += Subscription_OnDataChanged;
|
||||
|
||||
var result = subscription.AddOpcItem(item.Value.ToArray());
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (result.Count > 0)
|
||||
{
|
||||
foreach (var item1 in result)
|
||||
{
|
||||
stringBuilder.Append($"{item1.Item1.ItemID}:{item1.Item2}");
|
||||
}
|
||||
_logAction?.Invoke(3, this, $"添加变量失败:{stringBuilder}", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemDicts.AddOrUpdate(item.Key, item.Value.Where(a => !result.Select(b => b.Item1).Contains(a)).ToList());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"添加组失败:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Groups?.Count; i++)
|
||||
{
|
||||
var group = Groups[i];
|
||||
if (group != null)
|
||||
{
|
||||
if (group.OpcItems.Count == 0)
|
||||
{
|
||||
ItemDicts.Remove(group.Name);
|
||||
m_server.RemoveGroup(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置节点并保存,每次重连会自动添加节点
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, List<OpcItem>> AddItemsWithSave(List<string> items)
|
||||
{
|
||||
int i = 0;
|
||||
ItemDicts = items.ToList().ConvertAll(o => new OpcItem(o)).ChunkTrivialBetter(OPCNode.GroupSize).ToDictionary(a => "default" + (i++));
|
||||
return ItemDicts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接服务器
|
||||
/// </summary>
|
||||
public void Connect()
|
||||
{
|
||||
publicConnect = true;
|
||||
Interlocked.CompareExchange(ref IsExit, 0, 1);
|
||||
PrivateConnect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
Interlocked.CompareExchange(ref IsExit, 1, 0);
|
||||
PrivateDisconnect();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
PrivateDisconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"连接释放失败:{ex.Message}", ex);
|
||||
}
|
||||
Interlocked.CompareExchange(ref IsExit, 1, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 浏览节点
|
||||
/// </summary>
|
||||
/// <param name="itemId"></param>
|
||||
/// <returns></returns>
|
||||
public List<BrowseElement> GetBrowseElements(string itemId = null)
|
||||
{
|
||||
return this.m_server?.Browse(itemId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取服务状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ServerStatus GetServerStatus()
|
||||
{
|
||||
return this.m_server?.GetServerStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化设置
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
public void Init(OPCNode node)
|
||||
{
|
||||
if (node != null)
|
||||
OPCNode = node;
|
||||
checkTimer?.Stop();
|
||||
checkTimer?.Dispose();
|
||||
checkTimer = new Timer(OPCNode.CheckRate * 60 * 1000);
|
||||
checkTimer.Elapsed += CheckTimer_Elapsed;
|
||||
checkTimer.Start();
|
||||
try
|
||||
{
|
||||
m_server?.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"连接释放失败:{ex.Message}", ex);
|
||||
}
|
||||
m_server = new OpcServer(OPCNode.OPCName, OPCNode.OPCIP);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按OPC组读取组内变量,结果会在订阅事件中返回
|
||||
/// </summary>
|
||||
/// <param name="groupName">组名称,值为null时读取全部组</param>
|
||||
/// <returns></returns>
|
||||
public void ReadItemsWithGroup(string groupName = null)
|
||||
{
|
||||
PrivateConnect();
|
||||
{
|
||||
var groups = groupName != null ? Groups.Where(a => a.Name == groupName) : Groups;
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (group.OpcItems.Count > 0)
|
||||
{
|
||||
group.ReadAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public void RemoveItems(List<string> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (IsExit == 1) return;
|
||||
var opcGroups = Groups.Where(it => it.OpcItems.Any(a => a.ItemID == item));
|
||||
foreach (var opcGroup in opcGroups)
|
||||
{
|
||||
var tag = opcGroup.OpcItems.Where(a => item == a.ItemID);
|
||||
var result = opcGroup.RemoveItem(tag.ToArray());
|
||||
|
||||
if (opcGroup.OpcItems.Count == 0)
|
||||
{
|
||||
opcGroup.OnDataChanged -= Subscription_OnDataChanged;
|
||||
ItemDicts.Remove(opcGroup.Name);
|
||||
m_server.RemoveGroup(opcGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemDicts[opcGroup.Name].RemoveWhere(a => tag.Contains(a) && !result.Select(b => b.Item1).Contains(a));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
return OPCNode?.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量写入值
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, Tuple<bool, string>> WriteItem(Dictionary<string, object> writeInfos)
|
||||
{
|
||||
PrivateConnect();
|
||||
Dictionary<string, Tuple<bool, string>> results = new();
|
||||
|
||||
var valueGroup = writeInfos.GroupBy(itemId =>
|
||||
{
|
||||
var group = Groups.FirstOrDefault(it => it.OpcItems.Any(a => a.ItemID == itemId.Key));
|
||||
return group;
|
||||
}).ToList();
|
||||
|
||||
foreach (var item1 in valueGroup)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (item1.Key == null)
|
||||
{
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
results.AddOrUpdate(item2.Key, Tuple.Create(true, $"不存在该变量{item2.Key}"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<int> serverHandles = new();
|
||||
Dictionary<int, OpcItem> handleItems = new();
|
||||
List<object> values = new();
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
var opcItem = item1.Key.OpcItems.Where(it => it.ItemID == item2.Key).FirstOrDefault();
|
||||
serverHandles.Add(opcItem.ServerHandle);
|
||||
handleItems.AddOrUpdate(opcItem.ServerHandle, opcItem);
|
||||
var rawWriteValue = item2.Value;
|
||||
values.Add(rawWriteValue);
|
||||
}
|
||||
|
||||
var result = item1.Key.Write(values.ToArray(), serverHandles.ToArray());
|
||||
var data = item1.ToList();
|
||||
foreach (var item2 in result)
|
||||
{
|
||||
results.AddOrUpdate(handleItems[item2.Item1].ItemID, Tuple.Create(true, $"错误代码{item2.Item2}"));
|
||||
}
|
||||
}
|
||||
foreach (var item2 in item1)
|
||||
{
|
||||
results.AddOrUpdate(item2.Key, Tuple.Create(false, $"成功"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var keys = writeInfos.Keys.ToList();
|
||||
foreach (var item in keys)
|
||||
{
|
||||
results.AddOrUpdate(item, Tuple.Create(true, ex.Message));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
private void CheckTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
lock (checkLock)
|
||||
{
|
||||
|
||||
if (IsExit == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = m_server.GetServerStatus();
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsExit == 0 && publicConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
PrivateConnect();
|
||||
_logAction?.Invoke(1, this, $"重新链接成功", null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"重新链接失败:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var timeer = sender as Timer;
|
||||
timeer.Enabled = false;
|
||||
timeer.Stop();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void PrivateAddItems()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddItems(ItemDicts);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"添加点位失败:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
private void PrivateConnect()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
|
||||
if (m_server?.IsConnected == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = m_server.GetServerStatus();
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
var status1 = m_server.GetServerStatus();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
Init(OPCNode);
|
||||
m_server?.Connect();
|
||||
_logAction?.Invoke(1, this, $"{m_server.Host} - {m_server.Name} - 连接成功", null);
|
||||
PrivateAddItems();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Init(OPCNode);
|
||||
m_server?.Connect();
|
||||
_logAction?.Invoke(1, this, $"{m_server.Host} - {m_server.Name} - 连接成功", null);
|
||||
PrivateAddItems();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void PrivateDisconnect()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (IsConnected)
|
||||
_logAction?.Invoke(1, this, $"{m_server.Host} - {m_server.Name} - 断开连接", null);
|
||||
if (checkTimer != null)
|
||||
{
|
||||
checkTimer.Enabled = false;
|
||||
checkTimer.Stop();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
m_server?.Dispose();
|
||||
m_server = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logAction?.Invoke(3, this, $"连接释放失败:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Subscription_OnDataChanged(List<ItemReadResult> values)
|
||||
{
|
||||
DataChangedHandler?.Invoke(values);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCDA;
|
||||
/// <summary>
|
||||
/// OPCDA连接配置项
|
||||
/// </summary>
|
||||
public class OPCNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否订阅
|
||||
/// </summary>
|
||||
[Description("订阅")]
|
||||
public bool ActiveSubscribe { get; set; } = true;
|
||||
/// <summary>
|
||||
/// 内部检测重连间隔/min
|
||||
/// </summary>
|
||||
[Description("重连间隔/min")]
|
||||
public int CheckRate { get; set; } = 30;
|
||||
/// <summary>
|
||||
/// 死区
|
||||
/// </summary>
|
||||
[Description("死区")]
|
||||
public float DeadBand { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// 分组大小
|
||||
/// </summary>
|
||||
[Description("分组大小")]
|
||||
public int GroupSize { get; set; } = 500;
|
||||
/// <summary>
|
||||
/// OPCIP
|
||||
/// </summary>
|
||||
[Description("OPCIP")]
|
||||
public string OPCIP { get; set; } = "localhost";
|
||||
/// <summary>
|
||||
/// OPCNAME
|
||||
/// </summary>
|
||||
[Description("OPCNAME")]
|
||||
public string OPCName { get; set; } = "Kepware.KEPServerEX.V6";
|
||||
/// <summary>
|
||||
/// 订阅间隔
|
||||
/// </summary>
|
||||
[Description("订阅间隔")]
|
||||
public int UpdateRate { get; set; } = 1000;
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{(string.IsNullOrEmpty(OPCIP) ? "localhost" : OPCIP)}:{OPCName}";
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
</Project>
|
||||
@@ -1,579 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>ThingsGateway.Foundation.Adapter.OPCDA</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
|
||||
<summary>
|
||||
移除符合条件的元素
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="this"></param>
|
||||
<param name="where"></param>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_SYSTEM_DEFAULT">
|
||||
<summary>
|
||||
The WIN32 system default locale.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.LOCALE_USER_DEFAULT">
|
||||
<summary>
|
||||
The WIN32 user default locale.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.CreateInstance(System.Guid,System.String)">
|
||||
<summary>
|
||||
创建一个COM服务器的实例。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.GetSystemMessage(System.Int32)">
|
||||
<summary>
|
||||
指定错误消息文本检索系统。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.InitializeSecurity">
|
||||
<summary>
|
||||
初始化COM安全。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID)">
|
||||
<summary>
|
||||
从枚举器读取guid。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.ReadClasses(ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID)">
|
||||
<summary>
|
||||
从枚举器读取guid。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Comn.ComInterop.RealseComServer(System.Object)">
|
||||
<summary>
|
||||
释放 COM 对象
|
||||
</summary>
|
||||
<param name="m_server"></param>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.Comn.Convert.FILETIME_BaseTime">
|
||||
<summary>
|
||||
windows的filetime是从1601-1-1 00:00:00开始的,datetime是从1-1-1 00:00:00开始的
|
||||
datetime和filetime的滴答单位都是100ns(100纳秒,千万分之一秒),所以转换时只需要考虑开始时间即可
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnDataChangedHandler">
|
||||
<summary>
|
||||
值变化
|
||||
</summary>
|
||||
<param name="opcItems"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnReadCompletedHandler">
|
||||
<summary>
|
||||
读取
|
||||
</summary>
|
||||
<param name="opcItems"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OnWriteCompletedHandler">
|
||||
<summary>
|
||||
写入
|
||||
</summary>
|
||||
<param name="opcItems"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult">
|
||||
<summary>
|
||||
返回结果
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Name">
|
||||
<summary>
|
||||
ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Quality">
|
||||
<summary>
|
||||
Quality
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.TimeStamp">
|
||||
<summary>
|
||||
TimeStamp
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ItemReadResult.Value">
|
||||
<summary>
|
||||
Value
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.InitIoInterfaces(System.Object)">
|
||||
<summary>
|
||||
建立连接
|
||||
</summary>
|
||||
<param name="handle"></param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcGroup.ReadAsync">
|
||||
<summary>
|
||||
组读取
|
||||
</summary>
|
||||
<exception cref="T:System.Runtime.InteropServices.ExternalException"></exception>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem">
|
||||
<summary>
|
||||
OpcItem
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.#ctor(System.String)">
|
||||
<summary>
|
||||
OpcItem
|
||||
</summary>
|
||||
<param name="itemId"></param>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.AccessPath">
|
||||
<summary>
|
||||
AccessPath
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Blob">
|
||||
<summary>
|
||||
Blob
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.BlobSize">
|
||||
<summary>
|
||||
BlobSize
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ClientHandle">
|
||||
<summary>
|
||||
ClientHandle
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.IsActive">
|
||||
<summary>
|
||||
active(1) or not(0)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ItemID">
|
||||
<summary>
|
||||
数据项在opc server的完全名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Quality">
|
||||
<summary>
|
||||
Quality
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.RunTimeDataType">
|
||||
<summary>
|
||||
RunTimeDataType
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.ServerHandle">
|
||||
<summary>
|
||||
ServerHandle
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.TimeStamp">
|
||||
<summary>
|
||||
TimeStamp
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem.Value">
|
||||
<summary>
|
||||
Value
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.AddGroup(System.String,System.Boolean,System.Int32,System.Single)">
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.Browse(System.String)">
|
||||
<summary>
|
||||
获取节点
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcServer.GetServerStatus">
|
||||
<summary>
|
||||
服务器状态
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus">
|
||||
<summary>
|
||||
ServerStatus
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.CurrentTime">
|
||||
<summary>
|
||||
CurrentTime
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.LastUpdateTime">
|
||||
<summary>
|
||||
LastUpdateTime
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.ServerState">
|
||||
<summary>
|
||||
ServerState
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.StartTime">
|
||||
<summary>
|
||||
StartTime
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.VendorInfo">
|
||||
<summary>
|
||||
VendorInfo
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.Da.ServerStatus.Version">
|
||||
<summary>
|
||||
Version
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery">
|
||||
<summary>
|
||||
OpcDiscovery
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.Discovery.OpcDiscovery.GetOpcServer(System.String,System.String)">
|
||||
<summary>
|
||||
GetOpcServer
|
||||
</summary>
|
||||
<param name="serverName"></param>
|
||||
<param name="host"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPoint">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IConnectionPointContainer">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnectionPoints">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumConnections">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumGUID">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumString">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumUnknown">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCCommon">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCEnumGUID">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerList2">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCShutdown">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CONNECTDATA">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEDIRECTION">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEFILTER">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSETYPE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCDATASOURCE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCENUMSCOPE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCEUTYPE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCNAMESPACETYPE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer10">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer20">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_OPCDAServer30">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.CATID_XMLDAServer10">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IEnumOPCItemAttributes">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO2">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCAsyncIO3">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowse">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCBrowseServerAddressSpace">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCDataCallback">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCGroupStateMgt2">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemDeadbandMgt">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemIO">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemMgt">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemProperties">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCItemSamplingMgt">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCPublicGroupStateMgt">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServer">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCServerPublicGroups">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.IOPCSyncIO2">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCBROWSEELEMENT">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADER">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCGROUPHEADERWRITE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMATTRIBUTES">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMDEF">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER1">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADER2">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMHEADERWRITE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTIES">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMPROPERTY">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMRESULT">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMSTATE">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCITEMVQT">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.OPCSERVERSTATUS">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Constants">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Qualities">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.Rcw.Properties">
|
||||
<exclude />
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.DataChangedEventHandler">
|
||||
<summary>
|
||||
订阅变化项
|
||||
</summary>
|
||||
<param name="values"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient">
|
||||
<summary>
|
||||
OPCDAClient
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ItemDicts">
|
||||
<summary>
|
||||
当前保存的需订阅列表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.#ctor(ThingsGateway.Foundation.ILog)">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
<param name="logger"></param>
|
||||
</member>
|
||||
<member name="E:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.DataChangedHandler">
|
||||
<summary>
|
||||
数据变化事件
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.IsConnected">
|
||||
<summary>
|
||||
是否连接成功
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.OPCNode">
|
||||
<summary>
|
||||
当前配置
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItems(System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{ThingsGateway.Foundation.Adapter.OPCDA.Da.OpcItem}})">
|
||||
<summary>
|
||||
添加节点,需要在连接成功后执行
|
||||
</summary>
|
||||
<param name="items">组名称/变量节点,注意每次添加的组名称不能相同</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.AddItemsWithSave(System.Collections.Generic.List{System.String})">
|
||||
<summary>
|
||||
设置节点并保存,每次重连会自动添加节点
|
||||
</summary>
|
||||
<param name="items"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Connect">
|
||||
<summary>
|
||||
连接服务器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Disconnect">
|
||||
<summary>
|
||||
断开连接
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetBrowseElements(System.String)">
|
||||
<summary>
|
||||
浏览节点
|
||||
</summary>
|
||||
<param name="itemId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.GetServerStatus">
|
||||
<summary>
|
||||
获取服务状态
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Init(ThingsGateway.Foundation.Adapter.OPCDA.OPCNode)">
|
||||
<summary>
|
||||
初始化设置
|
||||
</summary>
|
||||
<param name="node"></param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ReadItemsWithGroup(System.String)">
|
||||
<summary>
|
||||
按OPC组读取组内变量,结果会在订阅事件中返回
|
||||
</summary>
|
||||
<param name="groupName">组名称,值为null时读取全部组</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.RemoveItems(System.Collections.Generic.List{System.String})">
|
||||
<summary>
|
||||
移除节点
|
||||
</summary>
|
||||
<param name="items"></param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.ToString">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.WriteItem(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken})">
|
||||
<summary>
|
||||
批量写入值
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode">
|
||||
<summary>
|
||||
OPCDA连接配置项
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ActiveSubscribe">
|
||||
<summary>
|
||||
是否订阅
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.CheckRate">
|
||||
<summary>
|
||||
内部检测重连间隔/min
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.DeadBand">
|
||||
<summary>
|
||||
死区
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.GroupSize">
|
||||
<summary>
|
||||
分组大小
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCIP">
|
||||
<summary>
|
||||
OPCIP
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.OPCName">
|
||||
<summary>
|
||||
OPCNAME
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.UpdateRate">
|
||||
<summary>
|
||||
订阅间隔
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCDA.OPCNode.ToString">
|
||||
<summary>
|
||||
<inheritdoc/>
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,17 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Linq;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
@@ -1,78 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
|
||||
/// <summary>
|
||||
/// OPCUAClient配置项
|
||||
/// </summary>
|
||||
public class OPCNode
|
||||
{
|
||||
/// <summary>
|
||||
/// OPCUrl
|
||||
/// </summary>
|
||||
[Description("OPCUrl")]
|
||||
public string OPCUrl { get; set; } = "opc.tcp://127.0.0.1:49320";
|
||||
/// <summary>
|
||||
/// 登录账号
|
||||
/// </summary>
|
||||
[Description("登录账号")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登录密码
|
||||
/// </summary>
|
||||
[Description("登录密码")]
|
||||
public string Password { get; set; }
|
||||
/// <summary>
|
||||
/// 检查域
|
||||
/// </summary>
|
||||
[Description("检查域")]
|
||||
public bool CheckDomain { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新间隔
|
||||
/// </summary>
|
||||
[Description("更新间隔")]
|
||||
public int UpdateRate { get; set; } = 1000;
|
||||
/// <summary>
|
||||
/// 是否订阅
|
||||
/// </summary>
|
||||
[Description("是否订阅")]
|
||||
public bool ActiveSubscribe { get; set; } = true;
|
||||
/// <summary>
|
||||
/// 分组大小
|
||||
/// </summary>
|
||||
[Description("分组大小")]
|
||||
public int GroupSize { get; set; } = 500;
|
||||
/// <summary>
|
||||
/// 死区
|
||||
/// </summary>
|
||||
[Description("死区")]
|
||||
public double DeadBand { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// KeepAliveInterval/ms
|
||||
/// </summary>
|
||||
[Description("KeepAliveInterval/ms")]
|
||||
public int KeepAliveInterval { get; set; } = 3000;
|
||||
/// <summary>
|
||||
/// 安全策略
|
||||
/// </summary>
|
||||
[Description("安全策略")]
|
||||
public bool IsUseSecurity { get; set; } = false;
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
return OPCUrl;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
using Opc.Ua;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
|
||||
/// <summary>
|
||||
/// 读取属性过程中用于描述的
|
||||
/// </summary>
|
||||
public class OPCNodeAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性的名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// 操作结果状态描述
|
||||
/// </summary>
|
||||
public StatusCode StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 属性的类型描述
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
/// <summary>
|
||||
/// 属性的值,如果读取错误,返回文本描述
|
||||
/// </summary>
|
||||
public object Value { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net48;net6.0;net7.0</TargetFrameworks>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" Version="1.4.372.56" />
|
||||
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes" Version="1.4.372.56" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,468 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>ThingsGateway.Foundation.Adapter.OPCUA</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.RemoveWhere``1(System.Collections.Generic.ICollection{``0},System.Func{``0,System.Boolean})">
|
||||
<summary>
|
||||
移除符合条件的元素
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="this"></param>
|
||||
<param name="where"></param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.CollectionExtensions.SelectAsync``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Threading.Tasks.Task{``1}})">
|
||||
<summary>
|
||||
异步Select
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<typeparam name="TResult"></typeparam>
|
||||
<param name="source"></param>
|
||||
<param name="selector"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils">
|
||||
<summary>
|
||||
辅助类
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.Browse(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean)">
|
||||
<summary>
|
||||
Browses the address space and returns the references found.
|
||||
</summary>
|
||||
<param name="session">The session.</param>
|
||||
<param name="nodesToBrowse">The set of browse operations to perform.</param>
|
||||
<param name="throwOnError">if set to <c>true</c> a exception will be thrown on an error.</param>
|
||||
<returns>
|
||||
The references found. Null if an error occurred.
|
||||
</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.PrepareBrowseNext(Opc.Ua.BrowseResultCollection)">
|
||||
<summary>
|
||||
Create the continuation point collection from the browse result
|
||||
collection for the BrowseNext service.
|
||||
</summary>
|
||||
<param name="browseResultCollection">The browse result collection to use.</param>
|
||||
<returns>The collection of continuation points for the BrowseNext service.</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescriptionCollection,System.Boolean,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
浏览地址空间
|
||||
</summary>
|
||||
<param name="session"></param>
|
||||
<param name="nodesToBrowse"></param>
|
||||
<param name="throwOnError"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseAsync(Opc.Ua.Client.ISession,Opc.Ua.BrowseDescription,System.Boolean,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
浏览地址空间
|
||||
</summary>
|
||||
<param name="session"></param>
|
||||
<param name="nodeToBrowse"></param>
|
||||
<param name="throwOnError"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.BrowseSuperTypesAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,System.Boolean)">
|
||||
<summary>
|
||||
浏览地址空间并返回指定类型的所有节点
|
||||
</summary>
|
||||
<param name="session"></param>
|
||||
<param name="typeId"></param>
|
||||
<param name="throwOnError"></param>
|
||||
<returns></returns>
|
||||
<exception cref="T:Opc.Ua.ServiceResultException"></exception>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForInstanceAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
|
||||
<summary>
|
||||
Collects the fields for the instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsForType(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId})">
|
||||
<summary>
|
||||
Collects the fields for the type.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ConstructEventAsync(Opc.Ua.Client.ISession,Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList,System.Collections.Generic.Dictionary{Opc.Ua.NodeId,System.Type},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.NodeId})">
|
||||
<summary>
|
||||
Constructs an event object from a notification.
|
||||
</summary>
|
||||
<param name="session">The session.</param>
|
||||
<param name="monitoredItem">The monitored item that produced the notification.</param>
|
||||
<param name="notification">The notification.</param>
|
||||
<param name="knownEventTypes">The known event types.</param>
|
||||
<param name="eventTypeMappings">Mapping between event types and known event types.</param>
|
||||
<returns>
|
||||
The event object. Null if the notification is not a valid event type.
|
||||
</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.DiscoverServers(Opc.Ua.ApplicationConfiguration)">
|
||||
<summary>
|
||||
Discovers the servers on the local machine.
|
||||
</summary>
|
||||
<param name="configuration">The configuration.</param>
|
||||
<returns>A list of server urls.</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.FindEventType(Opc.Ua.Client.MonitoredItem,Opc.Ua.EventFieldList)">
|
||||
<summary>
|
||||
Finds the type of the event for the notification.
|
||||
</summary>
|
||||
<param name="monitoredItem">The monitored item.</param>
|
||||
<param name="notification">The notification.</param>
|
||||
<returns>The NodeId of the EventType.</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAttributeDisplayText(Opc.Ua.Client.ISession,System.UInt32,Opc.Ua.Variant)">
|
||||
<summary>
|
||||
指定的属性的显示文本。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.SelectEndpoint(System.String,System.Boolean)">
|
||||
<summary>
|
||||
Finds the endpoint that best matches the current settings.
|
||||
</summary>
|
||||
<param name="discoveryUrl">The discovery URL.</param>
|
||||
<param name="useSecurity">if set to <c>true</c> select an endpoint that uses security.</param>
|
||||
<returns>The best available endpoint.</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.TranslateBrowsePaths(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.NamespaceTable,System.Threading.CancellationToken,System.String[])">
|
||||
<summary>
|
||||
返回一组相对路径的节点id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.CollectFieldsAsync(Opc.Ua.Client.ISession,Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection,Opc.Ua.SimpleAttributeOperandCollection,System.Collections.Generic.List{Opc.Ua.NodeId},System.Collections.Generic.Dictionary{Opc.Ua.NodeId,Opc.Ua.QualifiedNameCollection})">
|
||||
<summary>
|
||||
Collects the fields for the instance node.
|
||||
</summary>
|
||||
<param name="session">The session.</param>
|
||||
<param name="nodeId">The node id.</param>
|
||||
<param name="parentPath">The parent path.</param>
|
||||
<param name="fields">The event fields.</param>
|
||||
<param name="fieldNodeIds">The node id for the declaration of the field.</param>
|
||||
<param name="foundNodes">The table of found nodes.</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.ContainsPath(Opc.Ua.SimpleAttributeOperandCollection,Opc.Ua.QualifiedNameCollection)">
|
||||
<summary>
|
||||
判断指定的select子句包含的浏览路径。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetAccessLevelDisplayText(System.Byte)">
|
||||
<summary>
|
||||
访问级别属性的显示文本。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.FormUtils.GetEventNotifierDisplayText(System.Byte)">
|
||||
<summary>
|
||||
事件通知属性的显示文本
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils">
|
||||
<summary>
|
||||
扩展方法
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Decode(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
|
||||
<summary>
|
||||
解析获取DataValue
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecoderObject(Opc.Ua.IServiceMessageContext,Opc.Ua.NodeId,Opc.Ua.BuiltInType,System.Int32,Newtonsoft.Json.Linq.JToken)">
|
||||
<summary>
|
||||
解析获取object
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.DecodeRawData(Opc.Ua.JsonDecoder,Opc.Ua.BuiltInType,System.Int32,System.String)">
|
||||
<summary>
|
||||
DecodeRawData
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.Encode(Opc.Ua.IServiceMessageContext,Opc.Ua.BuiltInType,System.Object)">
|
||||
<summary>
|
||||
OPCUAValue解析为Jtoken
|
||||
</summary>
|
||||
<param name="Context"></param>
|
||||
<param name="type"></param>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CreateEncoder(Opc.Ua.IServiceMessageContext,System.IO.Stream,System.Boolean,System.Boolean,System.Boolean,System.Boolean)">
|
||||
<summary>
|
||||
CreateEncoder
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.JsonUtils.CalculateActualValueRank(Newtonsoft.Json.Linq.JToken)">
|
||||
<summary>
|
||||
维度
|
||||
</summary>
|
||||
<param name="jToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode">
|
||||
<summary>
|
||||
OPCUAClient配置项
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.OPCUrl">
|
||||
<summary>
|
||||
OPCUrl
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UserName">
|
||||
<summary>
|
||||
登录账号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.Password">
|
||||
<summary>
|
||||
登录密码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.CheckDomain">
|
||||
<summary>
|
||||
检查域
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.UpdateRate">
|
||||
<summary>
|
||||
更新间隔
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ActiveSubscribe">
|
||||
<summary>
|
||||
是否订阅
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.GroupSize">
|
||||
<summary>
|
||||
分组大小
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.DeadBand">
|
||||
<summary>
|
||||
死区
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.KeepAliveInterval">
|
||||
<summary>
|
||||
KeepAliveInterval/ms
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.IsUseSecurity">
|
||||
<summary>
|
||||
安全策略
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCNode.ToString">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.DataChangedEventHandler">
|
||||
<summary>
|
||||
订阅委托
|
||||
</summary>
|
||||
<param name="value"></param>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient">
|
||||
<summary>
|
||||
OPCUAClient
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCNode">
|
||||
<summary>
|
||||
当前配置
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ProductUri">
|
||||
<summary>
|
||||
ProductUri
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Variables">
|
||||
<summary>
|
||||
当前保存的变量名称列表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient._variableDicts">
|
||||
<summary>
|
||||
当前的变量名称/OPC变量节点
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.dic_subscriptions">
|
||||
<summary>
|
||||
当前的订阅组,组名称/组
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReConnectHandler">
|
||||
<summary>
|
||||
SessionReconnectHandler
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.#ctor(ThingsGateway.Foundation.ILog)">
|
||||
<summary>
|
||||
默认的构造函数,实例化一个新的OPC UA类
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.DataChangedHandler">
|
||||
<summary>
|
||||
订阅
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AppConfig">
|
||||
<summary>
|
||||
配置信息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Connected">
|
||||
<summary>
|
||||
连接状态
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.OPCUAName">
|
||||
<summary>
|
||||
OPCUAClient
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Session">
|
||||
<summary>
|
||||
当前活动会话。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.AddSubscriptionAsync(System.String,System.String[])">
|
||||
<summary>
|
||||
新增订阅,需要指定订阅组名称,订阅的tag名数组
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveAllSubscription">
|
||||
<summary>
|
||||
移除所有的订阅消息
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.RemoveSubscription(System.String)">
|
||||
<summary>
|
||||
移除订阅消息
|
||||
</summary>
|
||||
<param name="subscriptionName">组名称</param>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.BrowseNodeReferenceAsync(System.String)">
|
||||
<summary>
|
||||
浏览一个节点的引用
|
||||
</summary>
|
||||
<param name="tag">节点值</param>
|
||||
<returns>引用节点描述</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.CallMethodByNodeId(System.String,System.String,System.Object[])">
|
||||
<summary>
|
||||
调用服务器的方法
|
||||
</summary>
|
||||
<param name="tagParent">方法的父节点tag</param>
|
||||
<param name="tag">方法的节点tag</param>
|
||||
<param name="args">传递的参数</param>
|
||||
<returns>输出的结果值</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadHistoryRawDataValues(System.String,System.DateTime,System.DateTime,System.UInt32,System.Boolean,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
读取历史数据
|
||||
</summary>
|
||||
<param name="tag">节点的索引</param>
|
||||
<param name="start">开始时间</param>
|
||||
<param name="end">结束时间</param>
|
||||
<param name="count">读取的个数</param>
|
||||
<param name="containBound">是否包含边界</param>
|
||||
<param name="cancellationToken">cancellationToken</param>
|
||||
<returns>读取的数据列表</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync">
|
||||
<summary>
|
||||
连接到服务器
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Disconnect">
|
||||
<summary>
|
||||
断开连接。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ConnectAsync(System.String)">
|
||||
<summary>
|
||||
Creates a new session.
|
||||
</summary>
|
||||
<returns>The new session object.</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(System.String[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
从服务器读取值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.WriteNodeAsync(System.Collections.Generic.Dictionary{System.String,Newtonsoft.Json.Linq.JToken},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
异步写opc标签
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadJTokenValueAsync(Opc.Ua.NodeId[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
从服务器读取值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNodeAsync(System.String,System.Boolean,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
从服务器或缓存读取节点
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.String,System.UInt32,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
读取一个节点的所有属性
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributeAsync(System.Collections.Generic.List{System.String},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
读取节点的所有属性
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.ReadNoteAttributes(System.String)">
|
||||
<summary>
|
||||
读取一个节点的所有属性
|
||||
</summary>
|
||||
<param name="tag">节点信息</param>
|
||||
<returns>节点的特性值</returns>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Dispose(System.Boolean)">
|
||||
<inheritdoc/>
|
||||
</member>
|
||||
<member name="M:ThingsGateway.Foundation.Adapter.OPCUA.OPCUAClient.Server_ReconnectComplete(System.Object,System.EventArgs)">
|
||||
<summary>
|
||||
连接处理器连接事件处理完成。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute">
|
||||
<summary>
|
||||
读取属性过程中用于描述的
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Name">
|
||||
<summary>
|
||||
属性的名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.StatusCode">
|
||||
<summary>
|
||||
操作结果状态描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Type">
|
||||
<summary>
|
||||
属性的类型描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:ThingsGateway.Foundation.Adapter.OPCUA.OPCNodeAttribute.Value">
|
||||
<summary>
|
||||
属性的值,如果读取错误,返回文本描述
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,43 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
|
||||
|
||||
internal static class CollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除符合条件的元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="where"></param>
|
||||
internal static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
|
||||
{
|
||||
foreach (var obj in @this.Where(where).ToList())
|
||||
{
|
||||
@this.Remove(obj);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 异步Select
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
internal static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
|
||||
{
|
||||
return Task.WhenAll(source.Select(selector));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
#region copyright
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||||
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
// QQ群:605534569
|
||||
//------------------------------------------------------------------------------
|
||||
#endregion
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// API首页:http://rrqm_home.gitee.io/touchsocket/
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
|
||||
|
||||
/// <summary>
|
||||
/// DictionaryExtension
|
||||
/// </summary>
|
||||
internal static class DictionaryExtension
|
||||
{
|
||||
#region 字典扩展
|
||||
|
||||
/// <summary>
|
||||
/// 移除满足条件的项目。
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="pairs"></param>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
internal static int RemoveWhen<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> pairs, Func<KeyValuePair<TKey, TValue>, bool> func)
|
||||
{
|
||||
var list = new List<TKey>();
|
||||
foreach (var item in pairs)
|
||||
{
|
||||
if (func?.Invoke(item) == true)
|
||||
{
|
||||
list.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (pairs.TryRemove(item, out _))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#if NET45_OR_GREATER || NETSTANDARD2_0_OR_GREATER
|
||||
|
||||
/// <summary>
|
||||
/// 尝试添加
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool TryAdd<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey, TValue value)
|
||||
{
|
||||
if (dictionary.ContainsKey(tkey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
dictionary.Add(tkey, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 尝试添加
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
internal static void AddOrUpdate<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey, TValue value)
|
||||
{
|
||||
if (dictionary.ContainsKey(tkey))
|
||||
{
|
||||
dictionary[tkey] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(tkey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取值。如果键不存在,则返回默认值。
|
||||
/// </summary>
|
||||
/// <typeparam name="Tkey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="tkey"></param>
|
||||
/// <returns></returns>
|
||||
internal static TValue GetValue<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, Tkey tkey)
|
||||
{
|
||||
return dictionary.TryGetValue(tkey, out var value) ? value : default;
|
||||
}
|
||||
#endregion 字典扩展
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user