mirror of
https://gitee.com/ThingsGateway/ThingsGateway.git
synced 2025-10-25 04:33:09 +08:00
Compare commits
1586 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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.13</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,148 +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;
|
||||
|
||||
using ThingsGateway.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.Core.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.Core;
|
||||
@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.Core;
|
||||
@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.Core;
|
||||
@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.Core;
|
||||
@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,21 +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.Core;
|
||||
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,232 +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"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Title": "Mqtt",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/MqttClient",
|
||||
"Title": "MqttClient"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
""";
|
||||
Navs = dataString.FromJsonString<List<NavItem>>();
|
||||
|
||||
#if Pro
|
||||
var dataStringPro =
|
||||
"""
|
||||
[
|
||||
{
|
||||
"Title": "Melsec",
|
||||
"Children": [
|
||||
{
|
||||
"Href": "/QnA3E_Binary",
|
||||
"Title": "QnA3E_Binary"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,152 +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.Melsec\Page\QnA3E_BinaryDebugPage.razor.cs" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor.cs" />
|
||||
<Content Include="..\..\PluginPro\ThingsGateway.Plugin.Melsec\Page\QnA3E_BinaryDebugPage.razor" Link="Pages\Melsec\QnA3E_BinaryDebugPage.razor" />
|
||||
<ProjectReference Include="..\..\FoundationPro\ThingsGateway.Foundation.Adapter.Melsec\ThingsGateway.Foundation.Adapter.Melsec.csproj" />
|
||||
|
||||
|
||||
|
||||
<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" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\MqttRpcNameVaueWithId.cs" Link="Pages\Mqtt\MqttRpcNameVaueWithId.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor.cs" Link="Pages\Mqtt\MqttClientDebugPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor.cs" Link="Pages\Mqtt\MqttClientPage.razor.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\PrivateLogger.cs" Link="Pages\Mqtt\PrivateLogger.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClient.cs" Link="Pages\Mqtt\MqttRpcClient.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcClientExtensions.cs" Link="Pages\Mqtt\MqttRpcClientExtensions.cs" />
|
||||
<Compile Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\RpcClass\MqttRpcTopicPair.cs" Link="Pages\Mqtt\MqttRpcTopicPair.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 >
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.DLT645" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.Modbus" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCDA" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.OPCUA" Version="*" />
|
||||
<PackageReference Include="ThingsGateway.Foundation.Adapter.Siemens" Version="*" />
|
||||
<!--<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" />-->
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup >
|
||||
<ProjectReference Include="..\..\Web\ThingsGateway.Components\ThingsGateway.Components.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientDebugPage.razor" Link="Pages\Mqtt\MqttClientDebugPage.razor" />
|
||||
<Content Include="..\..\Plugin\ThingsGateway.Plugin.Mqtt\Page\MqttClientPage.razor" Link="Pages\Mqtt\MqttClientPage.razor" />
|
||||
<PackageReference Include="MQTTnet" Version="4.3.1.873" />
|
||||
</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.Core;
|
||||
@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,53 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>3.0.0.13</Version>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFrameworks>net45;netstandard2.0;net6.0;net7.0</TargetFrameworks>
|
||||
<Description>
|
||||
ThingsGateway.Foundation是工业设备通讯类库,归属于ThingsGateway边缘网关项目,说明文档:https://diego2098.gitee.io/thingsgateway-docs/
|
||||
</Description>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>Embedded</DebugType>
|
||||
<EmbedAllSources>True</EmbedAllSources>
|
||||
</PropertyGroup>
|
||||
|
||||
</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,480 +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_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,31 +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[] heads)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,480 +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_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,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.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,21 +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;
|
||||
|
||||
global using ThingsGateway.Foundation.Core;
|
||||
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,21 +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;
|
||||
|
||||
global using ThingsGateway.Foundation.Core;
|
||||
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,334 +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[1] <= 0x05)
|
||||
{
|
||||
if ((response.Length < response[2] + 3))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((response.Length < 6))
|
||||
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[1] <= 0x05)
|
||||
{
|
||||
if ((response.Length < response[2] + 5))
|
||||
return new OperResult<byte[], FilterResult>("数据长度不足" + response.ToHexString()) { Content2 = FilterResult.Cache };
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
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,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;
|
||||
|
||||
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,85 +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,31 +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[] heads)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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.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,184 +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.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 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, Task<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 async Task Received(SerialSession client, ReceivedDataEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestInfo = e.RequestInfo;
|
||||
//接收外部报文
|
||||
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 ((await 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 ((await 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,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
|
||||
|
||||
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[] heads)
|
||||
{
|
||||
BodyLength = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,184 +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.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[] heads)
|
||||
{
|
||||
if (heads == null || heads.Length <= 0) return false;
|
||||
HeadBytes = heads;
|
||||
|
||||
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,249 +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.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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.GetWaitingClient(new() { ThrowBreakException = 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.GetWaitingClient(new() { ThrowBreakException = 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.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, Task<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 async Task Received(SocketClient client, ReceivedDataEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestInfo = e.RequestInfo;
|
||||
//接收外部报文
|
||||
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 ((await 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 ((await 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[] heads)
|
||||
{
|
||||
if (heads == null || heads.Length != 6) return false;
|
||||
HeadBytes = heads;
|
||||
|
||||
int num = (HeadBytes[4] * 256) + HeadBytes[5];
|
||||
BodyLength = num;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,187 +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.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,169 +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;
|
||||
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.Core.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.Core.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,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;
|
||||
|
||||
@@ -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,4 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -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,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
|
||||
|
||||
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;
|
||||
/// <summary>
|
||||
/// 加载服务端数据类型
|
||||
/// </summary>
|
||||
[Description("加载服务端数据类型")]
|
||||
public bool LoadType { get; set; } = true;
|
||||
/// <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,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
File diff suppressed because it is too large
Load Diff
@@ -1,534 +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 Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Opc.Ua;
|
||||
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace ThingsGateway.Foundation.Adapter.OPCUA;
|
||||
/// <summary>
|
||||
/// 扩展方法
|
||||
/// </summary>
|
||||
public static class JsonUtils
|
||||
{
|
||||
#region Decode
|
||||
|
||||
/// <summary>
|
||||
/// 解析获取DataValue
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DataValue Decode(
|
||||
IServiceMessageContext Context,
|
||||
NodeId dataTypeId,
|
||||
BuiltInType builtInType,
|
||||
int valueRank,
|
||||
JToken json
|
||||
)
|
||||
{
|
||||
|
||||
var data = DecoderObject(Context, dataTypeId, builtInType, valueRank, json);
|
||||
var dataValue = new DataValue(new Variant(data));
|
||||
return dataValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 解析获取object
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static object DecoderObject(
|
||||
IServiceMessageContext Context,
|
||||
NodeId dataTypeId,
|
||||
BuiltInType builtInType,
|
||||
int valueRank,
|
||||
JToken json
|
||||
)
|
||||
{
|
||||
object newData;
|
||||
switch (builtInType)
|
||||
{
|
||||
case BuiltInType.ExtensionObject:
|
||||
newData = new
|
||||
{
|
||||
Value = new
|
||||
{
|
||||
TypeId = new { Id = dataTypeId.Identifier, Namespace = dataTypeId.NamespaceIndex },
|
||||
Body = json
|
||||
}
|
||||
}.ToJsonString();
|
||||
break;
|
||||
case BuiltInType.Variant:
|
||||
var type = TypeInfo.GetDataTypeId(GetSystemType(json.Type));
|
||||
newData = new
|
||||
{
|
||||
Value = new
|
||||
{
|
||||
Type = type.Identifier,
|
||||
Body = json
|
||||
}
|
||||
|
||||
}.ToJsonString();
|
||||
break;
|
||||
default:
|
||||
newData = new
|
||||
{
|
||||
Value = json
|
||||
}.ToJsonString();
|
||||
break;
|
||||
}
|
||||
|
||||
using var decoder = new JsonDecoder(newData.ToString(), Context);
|
||||
var data = DecodeRawData(decoder, builtInType, valueRank, "Value");
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DecodeRawData
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static object DecodeRawData(JsonDecoder decoder, BuiltInType builtInType, int ValueRank, string fieldName)
|
||||
{
|
||||
if (builtInType != 0)
|
||||
{
|
||||
if (ValueRank == ValueRanks.Scalar)
|
||||
{
|
||||
switch (builtInType)
|
||||
{
|
||||
case BuiltInType.Null: { var variant = decoder.ReadVariant(fieldName); return variant.Value; }
|
||||
case BuiltInType.Boolean: { return decoder.ReadBoolean(fieldName); }
|
||||
case BuiltInType.SByte: { return decoder.ReadSByte(fieldName); }
|
||||
case BuiltInType.Byte: { return decoder.ReadByte(fieldName); }
|
||||
case BuiltInType.Int16: { return decoder.ReadInt16(fieldName); }
|
||||
case BuiltInType.UInt16: { return decoder.ReadUInt16(fieldName); }
|
||||
case BuiltInType.Int32: { return decoder.ReadInt32(fieldName); }
|
||||
case BuiltInType.UInt32: { return decoder.ReadUInt32(fieldName); }
|
||||
case BuiltInType.Int64: { return decoder.ReadInt64(fieldName); }
|
||||
case BuiltInType.UInt64: { return decoder.ReadUInt64(fieldName); }
|
||||
case BuiltInType.Float: { return decoder.ReadFloat(fieldName); }
|
||||
case BuiltInType.Double: { return decoder.ReadDouble(fieldName); }
|
||||
case BuiltInType.String: { return decoder.ReadField(fieldName, out var cancellationToken) ? cancellationToken?.ToString() : null; }
|
||||
case BuiltInType.DateTime: { return decoder.ReadDateTime(fieldName); }
|
||||
case BuiltInType.Guid: { return decoder.ReadGuid(fieldName); }
|
||||
case BuiltInType.ByteString: { return decoder.ReadByteString(fieldName); }
|
||||
case BuiltInType.XmlElement: { return decoder.ReadXmlElement(fieldName); }
|
||||
case BuiltInType.NodeId: { return decoder.ReadNodeId(fieldName); }
|
||||
case BuiltInType.ExpandedNodeId: { return decoder.ReadExpandedNodeId(fieldName); }
|
||||
case BuiltInType.StatusCode: { return decoder.ReadStatusCode(fieldName); }
|
||||
case BuiltInType.QualifiedName: { return decoder.ReadQualifiedName(fieldName); }
|
||||
case BuiltInType.LocalizedText: { return decoder.ReadLocalizedText(fieldName); }
|
||||
case BuiltInType.ExtensionObject: { return decoder.ReadExtensionObject(fieldName); }
|
||||
case BuiltInType.DataValue: { return decoder.ReadDataValue(fieldName); }
|
||||
case BuiltInType.Enumeration:
|
||||
{
|
||||
Type type = TypeInfo.GetSystemType(builtInType, ValueRank);
|
||||
return type.IsEnum ? decoder.ReadEnumerated(fieldName, type) : decoder.ReadInt32(fieldName);
|
||||
}
|
||||
case BuiltInType.DiagnosticInfo: { return decoder.ReadDiagnosticInfo(fieldName); }
|
||||
case BuiltInType.Variant: { return decoder.ReadVariant(fieldName); }
|
||||
}
|
||||
}
|
||||
if (ValueRank >= ValueRanks.OneDimension)
|
||||
{
|
||||
return decoder.ReadArray(fieldName, ValueRank, builtInType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
/// <summary>
|
||||
/// OPCUAValue解析为Jtoken
|
||||
/// </summary>
|
||||
/// <param name="Context"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
internal static JToken Encode(
|
||||
IServiceMessageContext Context,
|
||||
BuiltInType type,
|
||||
object value
|
||||
)
|
||||
{
|
||||
//对于Integer,Int64,Number等会转化为string JValue!
|
||||
|
||||
using var encoder = CreateEncoder(Context, null, false);
|
||||
Encode(encoder, type, "Value", value);
|
||||
var textbuffer = encoder.CloseAndReturnText();
|
||||
using var stringReader = new StringReader(textbuffer);
|
||||
using var jsonReader = new JsonTextReader(stringReader);
|
||||
var jToken = JToken.Load(jsonReader);
|
||||
return jToken["Value"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CreateEncoder
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static OPCUAJsonEncoder CreateEncoder(
|
||||
IServiceMessageContext context,
|
||||
Stream stream,
|
||||
bool useReversibleEncoding = false,
|
||||
bool topLevelIsArray = false,
|
||||
bool includeDefaultValues = true,
|
||||
bool includeDefaultNumbers = true
|
||||
)
|
||||
{
|
||||
|
||||
return new OPCUAJsonEncoder(context, useReversibleEncoding, topLevelIsArray, stream)
|
||||
{
|
||||
IncludeDefaultValues = includeDefaultValues,
|
||||
IncludeDefaultNumberValues = includeDefaultNumbers
|
||||
};
|
||||
}
|
||||
|
||||
private static void Encode(OPCUAJsonEncoder encoder, BuiltInType builtInType, string fieldName, object value)
|
||||
{
|
||||
bool isArray = (value?.GetType().IsArray ?? false) && (builtInType != BuiltInType.ByteString);
|
||||
bool isCollection = (value is IList) && (builtInType != BuiltInType.ByteString);
|
||||
if (!isArray && !isCollection)
|
||||
{
|
||||
switch (builtInType)
|
||||
{
|
||||
case BuiltInType.Null: { encoder.WriteVariant(fieldName, new Variant(value)); return; }
|
||||
//case BuiltInType.Boolean: { encoder.WriteBoolean(fieldName, (bool)value); return; }
|
||||
//case BuiltInType.SByte: { encoder.WriteSByte(fieldName, (sbyte)value); return; }
|
||||
//case BuiltInType.Byte: { encoder.WriteByte(fieldName, (byte)value); return; }
|
||||
//case BuiltInType.Int16: { encoder.WriteInt16(fieldName, (short)value); return; }
|
||||
//case BuiltInType.UInt16: { encoder.WriteUInt16(fieldName, (ushort)value); return; }
|
||||
//case BuiltInType.Int32: { encoder.WriteInt32(fieldName, (int)value); return; }
|
||||
//case BuiltInType.UInt32: { encoder.WriteUInt32(fieldName, (uint)value); return; }
|
||||
//case BuiltInType.Int64: { encoder.WriteInt64(fieldName, (long)value); return; }
|
||||
//case BuiltInType.UInt64: { encoder.WriteUInt64(fieldName, (ulong)value); return; }
|
||||
//case BuiltInType.Float: { encoder.WriteFloat(fieldName, (float)value); return; }
|
||||
//case BuiltInType.Double: { encoder.WriteDouble(fieldName, (double)value); return; }
|
||||
|
||||
//case BuiltInType.Integer: { encoder.WriteInt64(fieldName, (long)value); return; }
|
||||
//case BuiltInType.Number: { encoder.WriteInt64(fieldName, (long)value); return; }
|
||||
//case BuiltInType.UInteger: { encoder.WriteUInt64(fieldName, (ulong)value); return; }
|
||||
//case BuiltInType.String: { encoder.WriteString(fieldName, value?.ToString()); return; }
|
||||
//case BuiltInType.DateTime: { encoder.WriteDateTime(fieldName, (DateTime)value); return; }
|
||||
case BuiltInType.Boolean:
|
||||
{
|
||||
encoder.WriteBoolean(fieldName, Convert.ToBoolean(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.SByte:
|
||||
{
|
||||
encoder.WriteSByte(fieldName, Convert.ToSByte(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Byte:
|
||||
{
|
||||
encoder.WriteByte(fieldName, Convert.ToByte(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Int16:
|
||||
{
|
||||
encoder.WriteInt16(fieldName, Convert.ToInt16(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.UInt16:
|
||||
{
|
||||
encoder.WriteUInt16(fieldName, Convert.ToUInt16(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Int32:
|
||||
{
|
||||
encoder.WriteInt32(fieldName, Convert.ToInt32(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.UInt32:
|
||||
{
|
||||
encoder.WriteUInt32(fieldName, Convert.ToUInt32(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Int64:
|
||||
{
|
||||
encoder.WriteInt64(fieldName, Convert.ToInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.UInt64:
|
||||
{
|
||||
encoder.WriteUInt64(fieldName, Convert.ToUInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Float:
|
||||
{
|
||||
encoder.WriteFloat(fieldName, Convert.ToSingle(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Double:
|
||||
{
|
||||
encoder.WriteDouble(fieldName, Convert.ToDouble(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Integer:
|
||||
{
|
||||
encoder.WriteInt64(fieldName, Convert.ToInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Number:
|
||||
{
|
||||
encoder.WriteInt64(fieldName, Convert.ToInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.UInteger:
|
||||
{
|
||||
encoder.WriteUInt64(fieldName, Convert.ToUInt64(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.String:
|
||||
{
|
||||
encoder.WriteString(fieldName, Convert.ToString(value));
|
||||
return;
|
||||
}
|
||||
case BuiltInType.DateTime:
|
||||
{
|
||||
encoder.WriteDateTime(fieldName, Convert.ToDateTime(value));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case BuiltInType.Guid: { encoder.WriteGuid(fieldName, (Uuid)value); return; }
|
||||
case BuiltInType.ByteString: { encoder.WriteByteString(fieldName, (byte[])value); return; }
|
||||
case BuiltInType.XmlElement: { encoder.WriteXmlElement(fieldName, (XmlElement)value); return; }
|
||||
case BuiltInType.NodeId: { encoder.WriteNodeId(fieldName, (NodeId)value); return; }
|
||||
case BuiltInType.ExpandedNodeId: { encoder.WriteExpandedNodeId(fieldName, (ExpandedNodeId)value); return; }
|
||||
case BuiltInType.StatusCode: { encoder.WriteStatusCode(fieldName, (StatusCode)value); return; }
|
||||
case BuiltInType.QualifiedName: { encoder.WriteQualifiedName(fieldName, (QualifiedName)value); return; }
|
||||
case BuiltInType.LocalizedText: { encoder.WriteLocalizedText(fieldName, (LocalizedText)value); return; }
|
||||
case BuiltInType.ExtensionObject: { encoder.WriteExtensionObject(fieldName, (ExtensionObject)value); return; }
|
||||
case BuiltInType.DataValue: { encoder.WriteDataValue(fieldName, (DataValue)value); return; }
|
||||
case BuiltInType.Enumeration:
|
||||
{
|
||||
if (value?.GetType().IsEnum == true)
|
||||
{
|
||||
encoder.WriteEnumerated(fieldName, (Enum)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
encoder.WriteEnumerated(fieldName, (Enumeration)value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case BuiltInType.Variant: { encoder.WriteVariant(fieldName, new Variant(value)); return; }
|
||||
case BuiltInType.DiagnosticInfo: { encoder.WriteDiagnosticInfo(fieldName, (DiagnosticInfo)value); return; }
|
||||
|
||||
//case BuiltInType.Boolean:
|
||||
//case BuiltInType.SByte:
|
||||
//case BuiltInType.Byte:
|
||||
//case BuiltInType.Int16:
|
||||
//case BuiltInType.UInt16:
|
||||
//case BuiltInType.Int32:
|
||||
//case BuiltInType.UInt32:
|
||||
//case BuiltInType.Int64:
|
||||
//case BuiltInType.UInt64:
|
||||
//case BuiltInType.Float:
|
||||
//case BuiltInType.Double:
|
||||
//case BuiltInType.String:
|
||||
//case BuiltInType.Number:
|
||||
//case BuiltInType.Integer:
|
||||
//case BuiltInType.UInteger:
|
||||
// { encoder.WriteString(fieldName, value?.ToString()); return; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array c = value as Array;
|
||||
encoder.WriteArray(fieldName, c, c.Rank, builtInType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region json
|
||||
|
||||
/// <summary>
|
||||
/// 维度
|
||||
/// </summary>
|
||||
/// <param name="jToken"></param>
|
||||
/// <returns></returns>
|
||||
internal static int CalculateActualValueRank(this JToken jToken)
|
||||
{
|
||||
if (jToken.Type != JTokenType.Array)
|
||||
return -1;
|
||||
|
||||
var jArray = jToken.ToArray();
|
||||
int numDimensions = 1;
|
||||
|
||||
while (jArray.GetElementsType() == JTokenType.Array)
|
||||
{
|
||||
jArray = jArray.Children().ToArray();
|
||||
numDimensions++;
|
||||
}
|
||||
return numDimensions;
|
||||
}
|
||||
private static bool ElementsHasSameType(this JToken[] jTokens)
|
||||
{
|
||||
var checkType = jTokens[0].Type == JTokenType.Integer ? JTokenType.Float : jTokens[0].Type;
|
||||
return jTokens
|
||||
.Select(x => (x.Type == JTokenType.Integer) ? JTokenType.Float : x.Type)
|
||||
.All(t => t == checkType);
|
||||
}
|
||||
|
||||
private static JTokenType GetElementsType(this JToken[] jTokens)
|
||||
{
|
||||
if (!jTokens.ElementsHasSameType())
|
||||
throw new Exception("The array sent must have the same type of element in each dimension");
|
||||
return jTokens.First().Type;
|
||||
}
|
||||
private static Type GetSystemType(JTokenType jsonType)
|
||||
{
|
||||
return jsonType switch
|
||||
{
|
||||
JTokenType.None => typeof(string),
|
||||
JTokenType.Object => typeof(string),
|
||||
JTokenType.Array => typeof(Array),
|
||||
JTokenType.Constructor => typeof(string),
|
||||
JTokenType.Property => typeof(string),
|
||||
JTokenType.Comment => typeof(string),
|
||||
JTokenType.Integer => typeof(long),
|
||||
JTokenType.Float => typeof(float),
|
||||
JTokenType.String => typeof(string),
|
||||
JTokenType.Boolean => typeof(bool),
|
||||
JTokenType.Null => typeof(string),
|
||||
JTokenType.Undefined => typeof(string),
|
||||
JTokenType.Date => typeof(DateTime),
|
||||
JTokenType.Raw => typeof(string),
|
||||
JTokenType.Bytes => typeof(byte[]),
|
||||
JTokenType.Guid => typeof(Guid),
|
||||
JTokenType.Uri => typeof(Uri),
|
||||
JTokenType.TimeSpan => typeof(TimeSpan),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Json序列化和反序列化
|
||||
/// <summary>
|
||||
/// 从字符串到json
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static object FromJsonString(this string json, Type type)
|
||||
{
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject(json, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从字符串到json
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
internal static T FromJsonString<T>(this string json)
|
||||
{
|
||||
return (T)FromJsonString(json, typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">反序列化类型</typeparam>
|
||||
/// <param name="datas">数据</param>
|
||||
/// <returns></returns>
|
||||
internal static T JsonDeserializeFromBytes<T>(byte[] datas)
|
||||
{
|
||||
return (T)JsonDeserializeFromBytes(datas, typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json反序列化
|
||||
/// </summary>
|
||||
/// <param name="datas"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static object JsonDeserializeFromBytes(byte[] datas, Type type)
|
||||
{
|
||||
return FromJsonString(Encoding.UTF8.GetString(datas), type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">反序列化类型</typeparam>
|
||||
/// <param name="path">文件路径</param>
|
||||
/// <returns></returns>
|
||||
internal static T JsonDeserializeFromFile<T>(string path)
|
||||
{
|
||||
return JsonDeserializeFromString<T>(File.ReadAllText(path));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="json">json字符串</param>
|
||||
/// <returns></returns>
|
||||
internal static T JsonDeserializeFromString<T>(string json)
|
||||
{
|
||||
return FromJsonString<T>(json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json序列化数据对象
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <returns></returns>
|
||||
internal static byte[] JsonSerializeToBytes(object obj)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(ToJsonString(obj));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Json序列化至文件
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="path"></param>
|
||||
internal static void JsonSerializeToFile(object obj, string path)
|
||||
{
|
||||
using (var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||
{
|
||||
var date = JsonSerializeToBytes(obj);
|
||||
fileStream.Write(date, 0, date.Length);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为Json
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="isIndented"></param>
|
||||
/// <returns></returns>
|
||||
internal static string ToJsonString(this object item, bool isIndented = false)
|
||||
{
|
||||
if (isIndented)
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented);
|
||||
else
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject(item);
|
||||
}
|
||||
#endregion Json序列化和反序列化
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user