Compare commits
586
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae787622d2 | ||
|
|
d248630ddc | ||
|
|
b15d0a0a08 | ||
|
|
683ca25aaf | ||
|
|
d3cc50b6e8 | ||
|
|
8c3c866eff | ||
|
|
78907de455 | ||
|
|
500adfa789 | ||
|
|
9658fc28bd | ||
|
|
42ad98ab1f | ||
|
|
bd0a876b5b | ||
|
|
806cf0d670 | ||
|
|
82a51293b9 | ||
|
|
4cd7867e04 | ||
|
|
6560278568 | ||
|
|
08a233b2c5 | ||
|
|
7aa92d4806 | ||
|
|
468bcf786e | ||
|
|
21324985db | ||
|
|
4529602d97 | ||
|
|
bce5af56e0 | ||
|
|
f8643c4de1 | ||
|
|
161b20fea7 | ||
|
|
882e894fba | ||
|
|
79c87bedfd | ||
|
|
b1324c567c | ||
|
|
d2627be55b | ||
|
|
2ba6092385 | ||
|
|
fee0651595 | ||
|
|
58fc16d70b | ||
|
|
ddf8996f01 | ||
|
|
0c2cc0dad2 | ||
|
|
1e0c65f213 | ||
|
|
c53a2d9078 | ||
|
|
6223bc925f | ||
|
|
aca1d79023 | ||
|
|
45d12dea6f | ||
|
|
2cee6cb0f2 | ||
|
|
e9cda221bb | ||
|
|
c6181a76ec | ||
|
|
cd24373c80 | ||
|
|
a464b1fc21 | ||
|
|
b8f6af7112 | ||
|
|
1c8d01562f | ||
|
|
2608ee4de6 | ||
|
|
e63f706f41 | ||
|
|
94cd07cd3c | ||
|
|
967ca817ba | ||
|
|
979637cc07 | ||
|
|
5c7ff08a78 | ||
|
|
a64d1a82ed | ||
|
|
bf1766f90a | ||
|
|
1b789ad5d5 | ||
|
|
a7404d0e24 | ||
|
|
a64327ac36 | ||
|
|
c886303458 | ||
|
|
38003592df | ||
|
|
82c2b17a1f | ||
|
|
2660c564a6 | ||
|
|
7e2b4ed908 | ||
|
|
c1960f2150 | ||
|
|
4124443f36 | ||
|
|
6bab62a062 | ||
|
|
c426df990c | ||
|
|
20614fb9e6 | ||
|
|
302431b64c | ||
|
|
db34c579d0 | ||
|
|
83afddc918 | ||
|
|
cf77faf972 | ||
|
|
684513ee59 | ||
|
|
45a6d59b5e | ||
|
|
73c8fecdf2 | ||
|
|
8c77df207a | ||
|
|
1c6f9af2bb | ||
|
|
0cfde7f06b | ||
|
|
d3c361b544 | ||
|
|
b35b7d92f9 | ||
|
|
52bd0d01ce | ||
|
|
eb4f7ad971 | ||
|
|
8677e49680 | ||
|
|
29faef86e3 | ||
|
|
6ef42fcc21 | ||
|
|
d2d41df155 | ||
|
|
6d2477be4a | ||
|
|
57152ae749 | ||
|
|
88b8bc5534 | ||
|
|
41408b30da | ||
|
|
136be96e1b | ||
|
|
0258e54b4e | ||
|
|
d3c8813012 | ||
|
|
b8e54e1fc9 | ||
|
|
054075a341 | ||
|
|
8d42232589 | ||
|
|
e4d4d75642 | ||
|
|
2b5a0ffe14 | ||
|
|
a0d53f9ec9 | ||
|
|
dfa8693be9 | ||
|
|
8157a752bd | ||
|
|
4dd805bb1c | ||
|
|
1e45f48c75 | ||
|
|
d833eca584 | ||
|
|
c966a7034c | ||
|
|
f051d51ae0 | ||
|
|
267159e0a9 | ||
|
|
26db172153 | ||
|
|
2e75f65b4a | ||
|
|
432cb91e5a | ||
|
|
b0083afa10 | ||
|
|
955b59a195 | ||
|
|
b904d0ca41 | ||
|
|
f34046df2a | ||
|
|
889782068e | ||
|
|
d12ee008db | ||
|
|
6c3c6cd0ef | ||
|
|
5803f06bdb | ||
|
|
a4acf30771 | ||
|
|
a4ef208233 | ||
|
|
be6b40b5cd | ||
|
|
8738edd0c5 | ||
|
|
c71fe75446 | ||
|
|
c619c7d3b8 | ||
|
|
f3e5527145 | ||
|
|
39941842d4 | ||
|
|
3488939995 | ||
|
|
0f2ef5a5bf | ||
|
|
55d2381e8a | ||
|
|
126322584f | ||
|
|
4d9ddef3ca | ||
|
|
7139cdbe80 | ||
|
|
93d7456ccd | ||
|
|
7a8ce7b6ab | ||
|
|
865528e344 | ||
|
|
02bb9ee9fa | ||
|
|
79de40515a | ||
|
|
e38c6c1199 | ||
|
|
dbb35a203e | ||
|
|
a88a094e86 | ||
|
|
ffaebbdf07 | ||
|
|
e7d04b55b3 | ||
|
|
8301971906 | ||
|
|
693cf7e4e2 | ||
|
|
2fa212e6ff | ||
|
|
a210a0d1f2 | ||
|
|
4cd191fcb2 | ||
|
|
e21833fb5f | ||
|
|
b746ceb34a | ||
|
|
83c1f0e817 | ||
|
|
a88a5a8db2 | ||
|
|
271200a8da | ||
|
|
b703297f5e | ||
|
|
637d1d021d | ||
|
|
dbe424b17a | ||
|
|
be0525a319 | ||
|
|
0ce130f0ef | ||
|
|
c1ee29cd06 | ||
|
|
28607e2729 | ||
|
|
f1bc71fb92 | ||
|
|
69b607f963 | ||
|
|
6ac3ea87ef | ||
|
|
38973e0030 | ||
|
|
37c89a4c9c | ||
|
|
0075362f92 | ||
|
|
38d28599ad | ||
|
|
c9a4b0f3ce | ||
|
|
b74f1fd644 | ||
|
|
26b7aa7e8b | ||
|
|
92f63e744d | ||
|
|
b0581d81ef | ||
|
|
540b9af871 | ||
|
|
d11f7107fe | ||
|
|
3c5a28f69d | ||
|
|
110b880304 | ||
|
|
7867044c0a | ||
|
|
88903f3dac | ||
|
|
4e223549ee | ||
|
|
2ea0df8faf | ||
|
|
061e85ca6b | ||
|
|
269e650b38 | ||
|
|
a3bfc7a43e | ||
|
|
c2ff40d816 | ||
|
|
eb09ae2eca | ||
|
|
d1b6247bb7 | ||
|
|
c5f52e06fa | ||
|
|
9700ba7900 | ||
|
|
bc72130d09 | ||
|
|
ad208f9633 | ||
|
|
ad2bfd3639 | ||
|
|
5e637ae02e | ||
|
|
63f8dd7467 | ||
|
|
aac3af8714 | ||
|
|
378917f59d | ||
|
|
76e7ccb4a6 | ||
|
|
953b02a6e8 | ||
|
|
71a66dca2d | ||
|
|
978c620287 | ||
|
|
8489dafdf7 | ||
|
|
cfc52f195b | ||
|
|
68a1eb9941 | ||
|
|
c1573390b5 | ||
|
|
5d60523e87 | ||
|
|
91c63e0792 | ||
|
|
0940df2f1a | ||
|
|
16a76720b8 | ||
|
|
7101fd679e | ||
|
|
86299da682 | ||
|
|
39b951b709 | ||
|
|
a475bd80f3 | ||
|
|
4e64bcd117 | ||
|
|
fbd0219a4a | ||
|
|
104a68d9dc | ||
|
|
33a5e479a9 | ||
|
|
5482d4ac96 | ||
|
|
0d984a77b3 | ||
|
|
7e95e18207 | ||
|
|
38fa86d243 | ||
|
|
4c1ce73de9 | ||
|
|
eea80d39c0 | ||
|
|
15dc325275 | ||
|
|
ca333d1772 | ||
|
|
a4ece06b05 | ||
|
|
992452052e | ||
|
|
75192bbd09 | ||
|
|
6199bd48c5 | ||
|
|
25434d70d4 | ||
|
|
de6dd45dcb | ||
|
|
74f2e99ed3 | ||
|
|
99b1f4a171 | ||
|
|
8c10aa3752 | ||
|
|
7170da4a70 | ||
|
|
842f009b42 | ||
|
|
7f30ca0cd1 | ||
|
|
93e207c211 | ||
|
|
64cafc088a | ||
|
|
8a0da27a07 | ||
|
|
5a8478e782 | ||
|
|
368cd95114 | ||
|
|
33ef914984 | ||
|
|
3eb0b87f0d | ||
|
|
c13cb725f0 | ||
|
|
c6d4a016b5 | ||
|
|
eda0644b4b | ||
|
|
711dfc03ef | ||
|
|
93459ccfab | ||
|
|
5b73835d94 | ||
|
|
009aefb7c9 | ||
|
|
d2e18d615d | ||
|
|
69b475eb77 | ||
|
|
9848b97082 | ||
|
|
0b429ffbc2 | ||
|
|
ef146efaf0 | ||
|
|
431061a685 | ||
|
|
b6edd9c0a0 | ||
|
|
2210bb8240 | ||
|
|
8d7c1adf37 | ||
|
|
3376ac41b4 | ||
|
|
f9181fee74 | ||
|
|
4c77d6c06e | ||
|
|
b7db39853b | ||
|
|
66157ba988 | ||
|
|
65ab19290f | ||
|
|
e7e6fc7920 | ||
|
|
94c7279da1 | ||
|
|
2136695b80 | ||
|
|
c0f9b0ffa0 | ||
|
|
c4ef22436f | ||
|
|
0b73871518 | ||
|
|
f7dc6fee5e | ||
|
|
ba848a167d | ||
|
|
dcb0bf9a88 | ||
|
|
f6433134c1 | ||
|
|
7e3df77b5b | ||
|
|
ff5954d85b | ||
|
|
08dff1272b | ||
|
|
c09e266b2c | ||
|
|
d5c8fd1c8f | ||
|
|
a34740e838 | ||
|
|
836ba5a41f | ||
|
|
545a747ebc | ||
|
|
23c83ab452 | ||
|
|
bc9e583c29 | ||
|
|
18cef617da | ||
|
|
4ee736cff5 | ||
|
|
4e40dc8601 | ||
|
|
a5a68ec457 | ||
|
|
e26d88d437 | ||
|
|
98ba7d2dee | ||
|
|
78835c1af6 | ||
|
|
2522d1da9f | ||
|
|
8983c01591 | ||
|
|
61b1320d4f | ||
|
|
2c8a0922d1 | ||
|
|
b078d9586d | ||
|
|
6e35de5f4d | ||
|
|
2dbe4cded4 | ||
|
|
10865c6878 | ||
|
|
ee1353fe54 | ||
|
|
5cefd7fc3a | ||
|
|
ab0e5ea82a | ||
|
|
b2276c086c | ||
|
|
4fa462661c | ||
|
|
2b30d0cf34 | ||
|
|
df2c56e6c4 | ||
|
|
a997c3d7be | ||
|
|
3c964f2aab | ||
|
|
c445b3e098 | ||
|
|
2ea2a2592e | ||
|
|
27072598cd | ||
|
|
4a2d4772d7 | ||
|
|
2bf00606d3 | ||
|
|
3773e1d96c | ||
|
|
19ddc753c7 | ||
|
|
0c41c750e8 | ||
|
|
4bfd5c8e11 | ||
|
|
f0fb70e38b | ||
|
|
6e5bcafec0 | ||
|
|
d5cb18c910 | ||
|
|
3a2069b255 | ||
|
|
80c651dbfd | ||
|
|
5a3b9b57c4 | ||
|
|
ead350eef3 | ||
|
|
b43657a4db | ||
|
|
8fffb9e366 | ||
|
|
0fdd229141 | ||
|
|
2f1ada3f5b | ||
|
|
988a8c6642 | ||
|
|
42ee9eaee3 | ||
|
|
3f28051d79 | ||
|
|
65f13cc868 | ||
|
|
cd8ba3cda3 | ||
|
|
a5936c8f19 | ||
|
|
2842425673 | ||
|
|
06a401a1ff | ||
|
|
3a2fc50fec | ||
|
|
38a58ed8b7 | ||
|
|
c7cba20de0 | ||
|
|
6311df49c3 | ||
|
|
f1d32a39ba | ||
|
|
224b53f774 | ||
|
|
1e2777c5e7 | ||
|
|
c3c21649fb | ||
|
|
99ccabc142 | ||
|
|
f1e6e94450 | ||
|
|
320cddb177 | ||
|
|
42002e3fa4 | ||
|
|
77cabfd712 | ||
|
|
c933e2d759 | ||
|
|
f3f0a46627 | ||
|
|
b5fb4c2947 | ||
|
|
f6cce9df3c | ||
|
|
c0385c0782 | ||
|
|
db43bdb652 | ||
|
|
6bdc10f4a7 | ||
|
|
9692dc7f4f | ||
|
|
6795793858 | ||
|
|
a2c564d789 | ||
|
|
3bc9e731e8 | ||
|
|
95c5f09238 | ||
|
|
0a45d66c0b | ||
|
|
96408eaef3 | ||
|
|
cae3ca7cdf | ||
|
|
c8adc093e0 | ||
|
|
4395516216 | ||
|
|
9281b52464 | ||
|
|
6571de7c32 | ||
|
|
a75d66e028 | ||
|
|
e839148a6f | ||
|
|
65b502a9b1 | ||
|
|
9cde62b2e2 | ||
|
|
cc86c38246 | ||
|
|
357df87f49 | ||
|
|
4b33da565c | ||
|
|
d11f855325 | ||
|
|
eef1f31a21 | ||
|
|
b878ee96a5 | ||
|
|
97eed27458 | ||
|
|
fe08550dc3 | ||
|
|
8a0ae8080f | ||
|
|
ab4025e55f | ||
|
|
22fffe602c | ||
|
|
e4c0219783 | ||
|
|
3362fdfaff | ||
|
|
6093db4502 | ||
|
|
5e7598667b | ||
|
|
4fe8729b85 | ||
|
|
b1dd6666f1 | ||
|
|
a3613889e1 | ||
|
|
7b87d63531 | ||
|
|
d838c78a8a | ||
|
|
7a8bef501a | ||
|
|
9863b54bc8 | ||
|
|
e57c6a6a02 | ||
|
|
afa215534c | ||
|
|
780d44166e | ||
|
|
35e4078dda | ||
|
|
47e09584f2 | ||
|
|
fc8e82c0e8 | ||
|
|
b729b08da2 | ||
|
|
3209ff303c | ||
|
|
41693d9c83 | ||
|
|
8f02f4ff31 | ||
|
|
1525bb7c1a | ||
|
|
2aeaf42325 | ||
|
|
bf4fb469da | ||
|
|
efd0515295 | ||
|
|
be8ac28bc7 | ||
|
|
56dc89ac82 | ||
|
|
62ffc94c49 | ||
|
|
50a38bc557 | ||
|
|
3e643854bc | ||
|
|
0daefb93bb | ||
|
|
f5731c67a0 | ||
|
|
d2ae5f3e83 | ||
|
|
c4d332b68b | ||
|
|
1daa0212ef | ||
|
|
1748a83ec8 | ||
|
|
b3d6b5a59f | ||
|
|
891795b101 | ||
|
|
a20b0761fd | ||
|
|
3b9e8d754d | ||
|
|
fed3281525 | ||
|
|
c1d966d86a | ||
|
|
b2d2f8c13b | ||
|
|
4e5e3d63e1 | ||
|
|
25602fb914 | ||
|
|
602d0d5308 | ||
|
|
f95198e40e | ||
|
|
d2b2bbb94b | ||
|
|
a4246c7ea4 | ||
|
|
498fc21412 | ||
|
|
3f07a506ad | ||
|
|
fb74e2d785 | ||
|
|
3a2290570d | ||
|
|
3b68e3f9fd | ||
|
|
3184b1da8e | ||
|
|
b70a10e697 | ||
|
|
3433bbbebe | ||
|
|
4c0a797e98 | ||
|
|
203c2498ac | ||
|
|
2023ea5221 | ||
|
|
cbb3d4f735 | ||
|
|
8acf219ba2 | ||
|
|
68884cd7df | ||
|
|
1629d82d65 | ||
|
|
17ab11bdf1 | ||
|
|
d2ef959f15 | ||
|
|
21b00e9b83 | ||
|
|
3d7aaaaa3d | ||
|
|
705f7760af | ||
|
|
3b385d592d | ||
|
|
cf6a16656b | ||
|
|
f50f9bfa5b | ||
|
|
77d8c95930 | ||
|
|
57c2019405 | ||
|
|
46432bc61b | ||
|
|
a4360f6993 | ||
|
|
97e0a764b8 | ||
|
|
7409af70ac | ||
|
|
783d51e71a | ||
|
|
a710ab7457 | ||
|
|
6a428e3c76 | ||
|
|
2e56b8e5cf | ||
|
|
1a4c18fa35 | ||
|
|
153d031125 | ||
|
|
5d4c7dfe68 | ||
|
|
021beeb47f | ||
|
|
1140d67c75 | ||
|
|
f0d26a36be | ||
|
|
6afb10351e | ||
|
|
2f3259d063 | ||
|
|
30a9396e4a | ||
|
|
2a94347f3e | ||
|
|
30f5e6c935 | ||
|
|
0ad8bc6d75 | ||
|
|
c076d6b343 | ||
|
|
64e32751c0 | ||
|
|
279c8eefb4 | ||
|
|
b931ed62ff | ||
|
|
05665288ab | ||
|
|
8af89136e7 | ||
|
|
5b6461fa0a | ||
|
|
1f51924bc8 | ||
|
|
b1f3b72a96 | ||
|
|
dfc0661300 | ||
|
|
f747755301 | ||
|
|
ad2c1d615f | ||
|
|
11ad6d39ee | ||
|
|
0f394f622b | ||
|
|
09c542e1e6 | ||
|
|
d772a3d531 | ||
|
|
87206ebe79 | ||
|
|
f4c77feeef | ||
|
|
ae6d77efc1 | ||
|
|
8318ed33e1 | ||
|
|
c4c86b36d2 | ||
|
|
990b695db6 | ||
|
|
33f050ef71 | ||
|
|
026a95e3ac | ||
|
|
4fd9030812 | ||
|
|
45d138ece3 | ||
|
|
4a884a09a1 | ||
|
|
a524915f28 | ||
|
|
7982526790 | ||
|
|
b866c45e9b | ||
|
|
0073ac8b9e | ||
|
|
36d661c75e | ||
|
|
e3f1f2711b | ||
|
|
f9ae8c54e1 | ||
|
|
ad7abe5471 | ||
|
|
a027f3f544 | ||
|
|
0930df5e64 | ||
|
|
1c5bf76bb3 | ||
|
|
d2d697ae80 | ||
|
|
60f30e4c41 | ||
|
|
ecccfab7a6 | ||
|
|
1691c634c6 | ||
|
|
900a2d660c | ||
|
|
eaf60f3292 | ||
|
|
bc0de96ad9 | ||
|
|
a770f5a9b8 | ||
|
|
0fbc9e2bad | ||
|
|
ed5cd89d6a | ||
|
|
dd5b20ab38 | ||
|
|
3f35506b26 | ||
|
|
1ee7e00928 | ||
|
|
ffbfd5ebd5 | ||
|
|
7a2afd1bdc | ||
|
|
30f9ea19dd | ||
|
|
2ec8683b27 | ||
|
|
4f59f23c6f | ||
|
|
daac273edb | ||
|
|
edb084260f | ||
|
|
8370c7c2e7 | ||
|
|
4a394cc5d5 | ||
|
|
f4db55cc0b | ||
|
|
b4f41a2f1f | ||
|
|
5b9156d670 | ||
|
|
bebb83f6fc | ||
|
|
130b59fc91 | ||
|
|
b2a7cfb0d4 | ||
|
|
b67857f658 | ||
|
|
046fab05c0 | ||
|
|
6004a65572 | ||
|
|
0962efd159 | ||
|
|
cb1a471248 | ||
|
|
8da049219a | ||
|
|
91b55eb19c | ||
|
|
6b582bea64 | ||
|
|
61910932c2 | ||
|
|
1ecf528ff0 | ||
|
|
9a5ee99a82 | ||
|
|
cf626d7b91 | ||
|
|
b9e8eeab00 | ||
|
|
b880b62924 | ||
|
|
36f8bfa32f | ||
|
|
8be3b53db4 | ||
|
|
95759e70b4 | ||
|
|
2e6a17121f | ||
|
|
ed21db65c3 | ||
|
|
d29a425880 | ||
|
|
a4139d7a73 | ||
|
|
a6a517b6ea | ||
|
|
07f36f2945 | ||
|
|
e2048ed64c | ||
|
|
90b62779fd | ||
|
|
1c6488d621 | ||
|
|
62e9f612fc | ||
|
|
9e9a01bd43 | ||
|
|
6dcd40c640 | ||
|
|
b54de856af | ||
|
|
118ce9797f | ||
|
|
36ae8479ca | ||
|
|
9ca9d41ddc | ||
|
|
4f26815e68 | ||
|
|
abd68f9a44 | ||
|
|
ae8a0ca4c1 | ||
|
|
ac5684a2b5 | ||
|
|
0f738be73e | ||
|
|
4b85db202e | ||
|
|
96c300d34f | ||
|
|
dbdf1f8fb6 | ||
|
|
6158ee93dc | ||
|
|
6270e0c417 | ||
|
|
67ba9986f2 | ||
|
|
d2e8f4f0e3 | ||
|
|
c9ea85b7b8 | ||
|
|
86ed8b13bf |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Root Type="DevExpress.CodeRush.Foundation.CodePlaces.Options.FavoritesListContainer">
|
||||
<Options Language="Neutral">
|
||||
<Groups />
|
||||
</Options>
|
||||
</Root>
|
||||
+103
-4
@@ -1,3 +1,12 @@
|
||||
# Generated build outputs for all projects, including Debug/Release archives.
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Generated test results and hardware diagnostic captures.
|
||||
[Tt]est[Rr]esults/
|
||||
|
||||
AppDiagnostic/bin/
|
||||
AppDiagnostic/obj/
|
||||
Common/bin/
|
||||
Common/obj/
|
||||
Config/bin/
|
||||
@@ -26,8 +35,14 @@ GenericTest/bin/
|
||||
GenericTest/obj/
|
||||
GraphLib/bin/
|
||||
GraphLib/obj/
|
||||
LabelPrinting/bin/
|
||||
LabelPrinting/obj/
|
||||
MergeResultsDBs/bin/
|
||||
MergeResultsDBs/obj/
|
||||
NfcC7_Dll/bin/
|
||||
NfcC7_Dll/obj/
|
||||
NfcC7_DLL.Tests/bin/
|
||||
NfcC7_DLL.Tests/obj/
|
||||
OrderManagement/bin/
|
||||
OrderManagement/obj/
|
||||
ProductionTracing/bin/
|
||||
@@ -44,14 +59,20 @@ ResultsBrowser/bin/
|
||||
ResultsBrowser/obj/
|
||||
ResultsParser/bin/
|
||||
ResultsParser/obj/
|
||||
SharedDatabase/bin
|
||||
SharedDatabase/obj
|
||||
SchematicDrawing/bin
|
||||
SchematicDrawing/obj
|
||||
S640TestApp/bin/
|
||||
S640TestApp/obj/
|
||||
SharedComponents/bin/
|
||||
SharedComponents/obj/
|
||||
SharedDatabase/bin/
|
||||
SharedDatabase/obj/
|
||||
SchematicDrawing/bin/
|
||||
SchematicDrawing/obj/
|
||||
Statistics/bin/
|
||||
Statistics/obj/
|
||||
TBF/bin/
|
||||
TBF/obj/
|
||||
TBFTests/bin/
|
||||
TBFTests/obj/
|
||||
ToFirstMonitor/bin/
|
||||
ToFirstMonitor/obj/
|
||||
ToSecondMonitor/bin/
|
||||
@@ -62,6 +83,84 @@ WorkflowConfigurator/bin/
|
||||
WorkflowConfigurator/obj/
|
||||
Workplace/bin/
|
||||
Workplace/obj/
|
||||
DataStreamInterfaceTest/bin/
|
||||
DataStreamInterfaceTest/obj/
|
||||
DataStreamMeter/bin/
|
||||
DataStreamMeter/obj/
|
||||
Events/bin/
|
||||
Events/obj/
|
||||
TracingDB/bin/
|
||||
TracingDB/obj/
|
||||
Users/bin/
|
||||
Users/obj/
|
||||
.vs/
|
||||
.idea/
|
||||
*.suo
|
||||
*.bak
|
||||
TBF.sln.DotSettings.user
|
||||
/ExternalProjects
|
||||
/GenesisCordonelTester
|
||||
/packages/*
|
||||
!/packages/Common/
|
||||
/GenesisCordonelInterface/bin/Debug/GenesisCordonelInterfaceLogger.log
|
||||
/GenesisCordonelInterface/bin/Debug/GenesisCordonelTesterLogger.log
|
||||
/GenesisCordonelInterface/bin/Debug/SirtConfig.json
|
||||
/GenesisCordonelInterface/bin/Release
|
||||
/GenesisCordonelInterface/obj/Debug
|
||||
/GenesisCordonelInterface/obj/Release
|
||||
/ExternalProjects
|
||||
/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.dll
|
||||
/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.pdb
|
||||
/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfo.cs
|
||||
/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache
|
||||
/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache
|
||||
/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.dll
|
||||
/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Metrology.Measurements.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Metrology.Measurements.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Ui.CordonelPreadjustmentUi.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Ui.CordonelPreadjustmentUi.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Ui.GenesisToolBox.exe
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Ui.GenesisToolBox.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/XylemCommonUiLegacyGenCtl.dll
|
||||
/GenesisCordonelInterface/bin/Debug/XylemCommonUiLegacyGenCtl.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/de/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.resources.dll
|
||||
/GenesisCordonelInterface/bin/Debug/GenesisCordonelInterface.exe
|
||||
/GenesisCordonelInterface/bin/Debug/GenesisCordonelInterface.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/TempFlansh.exe
|
||||
/GenesisCordonelInterface/bin/Debug/TempFlansh.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.eRegister.eRegisterCore.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.eRegister.eRegisterCore.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxConfig.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxConfig.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Logic.RelatePcb.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Logic.RelatePcb.pdb
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Logic.ServiceCore.dll
|
||||
/GenesisCordonelInterface/bin/Debug/Xylem.Common.Logic.ServiceCore.pdb
|
||||
/GenesisCordonelInterface/RuntimePackage/Package
|
||||
/SharedComponents/obj/SharedComponents.csproj.nuget.g.props
|
||||
/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfo.cs
|
||||
/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache
|
||||
/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache
|
||||
/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.dll
|
||||
/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.pdb
|
||||
/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.dll
|
||||
/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.pdb
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<RootNamespace>AppDiagnostic.Logging</RootNamespace>
|
||||
<AssemblyName>AppDiagnostic.Logging</AssemblyName>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<ProjectGuid>{A7AF8ED2-362E-4DBB-B607-EBA2820719EC}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Layouts;
|
||||
|
||||
namespace AppDiagnostic.Logging
|
||||
{
|
||||
public static class AppDiagnosticConnector
|
||||
{
|
||||
private static readonly object syncRoot = new object();
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
LoggingConfiguration configuration = LogManager.Configuration ?? new LoggingConfiguration();
|
||||
NLog.Targets.Target existingTarget = configuration.FindTargetByName("appDiagnostic");
|
||||
|
||||
if (existingTarget != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var target = new AppDiagnosticTarget
|
||||
{
|
||||
Name = "appDiagnostic",
|
||||
PipeName = DiagnosticProtocol.DefaultPipeName,
|
||||
QueueLimit = DiagnosticProtocol.DefaultQueueLimit,
|
||||
ReconnectDelayMilliseconds = DiagnosticProtocol.DefaultReconnectDelayMilliseconds,
|
||||
ConnectTimeoutMilliseconds = DiagnosticProtocol.DefaultConnectTimeoutMilliseconds,
|
||||
Layout = new SimpleLayout("${message}")
|
||||
};
|
||||
|
||||
configuration.AddTarget(target.Name, target);
|
||||
configuration.AddRule(LogLevel.Trace, LogLevel.Fatal, target, "*");
|
||||
|
||||
LogManager.Configuration = configuration;
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
using NLog;
|
||||
using NLog.Targets;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AppDiagnostic.Logging
|
||||
{
|
||||
[Target("AppDiagnostic")]
|
||||
public sealed class AppDiagnosticTarget : TargetWithLayout
|
||||
{
|
||||
private readonly object connectionLock = new object();
|
||||
private readonly string applicationName;
|
||||
private readonly int processId;
|
||||
|
||||
private BlockingCollection<DiagnosticLogEntry> queue;
|
||||
private CancellationTokenSource cancellation;
|
||||
private Task senderTask;
|
||||
private NamedPipeClientStream pipeClient;
|
||||
|
||||
public AppDiagnosticTarget()
|
||||
{
|
||||
using (Process process = Process.GetCurrentProcess())
|
||||
{
|
||||
applicationName = process.ProcessName;
|
||||
processId = process.Id;
|
||||
}
|
||||
|
||||
PipeName = DiagnosticProtocol.DefaultPipeName;
|
||||
QueueLimit = DiagnosticProtocol.DefaultQueueLimit;
|
||||
ReconnectDelayMilliseconds =
|
||||
DiagnosticProtocol.DefaultReconnectDelayMilliseconds;
|
||||
ConnectTimeoutMilliseconds =
|
||||
DiagnosticProtocol.DefaultConnectTimeoutMilliseconds;
|
||||
}
|
||||
|
||||
public string PipeName { get; set; }
|
||||
|
||||
public int QueueLimit { get; set; }
|
||||
|
||||
public int ReconnectDelayMilliseconds { get; set; }
|
||||
|
||||
public int ConnectTimeoutMilliseconds { get; set; }
|
||||
|
||||
protected override void InitializeTarget()
|
||||
{
|
||||
base.InitializeTarget();
|
||||
|
||||
int queueLimit = QueueLimit > 0
|
||||
? QueueLimit
|
||||
: DiagnosticProtocol.DefaultQueueLimit;
|
||||
|
||||
queue = new BlockingCollection<DiagnosticLogEntry>(queueLimit);
|
||||
cancellation = new CancellationTokenSource();
|
||||
|
||||
senderTask = Task.Factory.StartNew(
|
||||
ProcessQueue,
|
||||
cancellation.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
protected override void Write(LogEventInfo logEvent)
|
||||
{
|
||||
if (logEvent == null || queue == null || queue.IsAddingCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = new DiagnosticLogEntry
|
||||
{
|
||||
TimestampUtc = logEvent.TimeStamp.ToUniversalTime(),
|
||||
MachineName = Environment.MachineName,
|
||||
ApplicationName = applicationName,
|
||||
ProcessId = processId,
|
||||
LoggerName = logEvent.LoggerName ?? string.Empty,
|
||||
Level = logEvent.Level?.Name ?? string.Empty,
|
||||
Message = Layout != null
|
||||
? Layout.Render(logEvent)
|
||||
: logEvent.FormattedMessage,
|
||||
Exception = logEvent.Exception?.ToString() ?? string.Empty
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
queue.TryAdd(entry);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// A concurrent NLog shutdown may dispose the queue.
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// A concurrent NLog shutdown may complete the queue.
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CloseTarget()
|
||||
{
|
||||
BlockingCollection<DiagnosticLogEntry> currentQueue = queue;
|
||||
CancellationTokenSource currentCancellation = cancellation;
|
||||
|
||||
if (currentQueue != null)
|
||||
{
|
||||
currentQueue.CompleteAdding();
|
||||
}
|
||||
|
||||
if (currentCancellation != null)
|
||||
{
|
||||
currentCancellation.Cancel();
|
||||
}
|
||||
|
||||
CloseConnection();
|
||||
|
||||
try
|
||||
{
|
||||
senderTask?.Wait(2000);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
// Cancellation during application shutdown is expected.
|
||||
}
|
||||
|
||||
currentQueue?.Dispose();
|
||||
currentCancellation?.Dispose();
|
||||
|
||||
queue = null;
|
||||
cancellation = null;
|
||||
senderTask = null;
|
||||
|
||||
base.CloseTarget();
|
||||
}
|
||||
|
||||
private void ProcessQueue()
|
||||
{
|
||||
CancellationToken token = cancellation.Token;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (DiagnosticLogEntry entry in
|
||||
queue.GetConsumingEnumerable(token))
|
||||
{
|
||||
SendWhenConnected(entry, token);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Target shutdown is expected to cancel the sender.
|
||||
}
|
||||
}
|
||||
|
||||
private void SendWhenConnected(
|
||||
DiagnosticLogEntry entry,
|
||||
CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
EnsureConnected();
|
||||
DiagnosticMessageSerializer.WriteFramed(pipeClient, entry);
|
||||
return;
|
||||
}
|
||||
catch (Exception exception) when (
|
||||
exception is IOException ||
|
||||
exception is TimeoutException ||
|
||||
exception is InvalidOperationException)
|
||||
{
|
||||
CloseConnection();
|
||||
|
||||
int delay = ReconnectDelayMilliseconds > 0
|
||||
? ReconnectDelayMilliseconds
|
||||
: DiagnosticProtocol.DefaultReconnectDelayMilliseconds;
|
||||
|
||||
if (token.WaitHandle.WaitOne(delay))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureConnected()
|
||||
{
|
||||
lock (connectionLock)
|
||||
{
|
||||
if (pipeClient != null && pipeClient.IsConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CloseConnectionWithoutLock();
|
||||
|
||||
pipeClient = new NamedPipeClientStream(
|
||||
".",
|
||||
string.IsNullOrWhiteSpace(PipeName)
|
||||
? DiagnosticProtocol.DefaultPipeName
|
||||
: PipeName,
|
||||
PipeDirection.Out,
|
||||
PipeOptions.Asynchronous);
|
||||
|
||||
int timeout = ConnectTimeoutMilliseconds > 0
|
||||
? ConnectTimeoutMilliseconds
|
||||
: DiagnosticProtocol.DefaultConnectTimeoutMilliseconds;
|
||||
|
||||
pipeClient.Connect(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseConnection()
|
||||
{
|
||||
lock (connectionLock)
|
||||
{
|
||||
CloseConnectionWithoutLock();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseConnectionWithoutLock()
|
||||
{
|
||||
if (pipeClient == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pipeClient.Dispose();
|
||||
pipeClient = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace AppDiagnostic.Logging
|
||||
{
|
||||
[DataContract]
|
||||
public sealed class DiagnosticLogEntry
|
||||
{
|
||||
[DataMember(Order = 1)]
|
||||
public DateTime TimestampUtc { get; set; }
|
||||
|
||||
[DataMember(Order = 2)]
|
||||
public string MachineName { get; set; }
|
||||
|
||||
[DataMember(Order = 3)]
|
||||
public string ApplicationName { get; set; }
|
||||
|
||||
[DataMember(Order = 4)]
|
||||
public int ProcessId { get; set; }
|
||||
|
||||
[DataMember(Order = 5)]
|
||||
public string LoggerName { get; set; }
|
||||
|
||||
[DataMember(Order = 6)]
|
||||
public string Level { get; set; }
|
||||
|
||||
[DataMember(Order = 7)]
|
||||
public string Message { get; set; }
|
||||
|
||||
[DataMember(Order = 8)]
|
||||
public string Exception { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Json;
|
||||
|
||||
namespace AppDiagnostic.Logging
|
||||
{
|
||||
public static class DiagnosticMessageSerializer
|
||||
{
|
||||
private static readonly DataContractJsonSerializer Serializer =
|
||||
new DataContractJsonSerializer(typeof(DiagnosticLogEntry));
|
||||
|
||||
private static readonly object SerializerLock = new object();
|
||||
|
||||
public static byte[] Serialize(DiagnosticLogEntry entry)
|
||||
{
|
||||
if (entry == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(entry));
|
||||
}
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
lock (SerializerLock)
|
||||
{
|
||||
Serializer.WriteObject(stream, entry);
|
||||
}
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static DiagnosticLogEntry Deserialize(byte[] payload)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(payload));
|
||||
}
|
||||
|
||||
if (payload.Length == 0 ||
|
||||
payload.Length > DiagnosticProtocol.MaximumMessageSize)
|
||||
{
|
||||
throw new InvalidDataException("Invalid diagnostic message size.");
|
||||
}
|
||||
|
||||
using (var stream = new MemoryStream(payload, false))
|
||||
{
|
||||
lock (SerializerLock)
|
||||
{
|
||||
return (DiagnosticLogEntry)Serializer.ReadObject(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteFramed(Stream stream, DiagnosticLogEntry entry)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
byte[] payload = Serialize(entry);
|
||||
|
||||
if (payload.Length > DiagnosticProtocol.MaximumMessageSize)
|
||||
{
|
||||
throw new InvalidDataException("Diagnostic message is too large.");
|
||||
}
|
||||
|
||||
byte[] length = BitConverter.GetBytes(payload.Length);
|
||||
stream.Write(length, 0, length.Length);
|
||||
stream.Write(payload, 0, payload.Length);
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
public static DiagnosticLogEntry ReadFramed(Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
byte[] lengthBuffer = ReadExactly(stream, sizeof(int));
|
||||
int payloadLength = BitConverter.ToInt32(lengthBuffer, 0);
|
||||
|
||||
if (payloadLength <= 0 ||
|
||||
payloadLength > DiagnosticProtocol.MaximumMessageSize)
|
||||
{
|
||||
throw new InvalidDataException("Invalid diagnostic message size.");
|
||||
}
|
||||
|
||||
return Deserialize(ReadExactly(stream, payloadLength));
|
||||
}
|
||||
|
||||
private static byte[] ReadExactly(Stream stream, int count)
|
||||
{
|
||||
byte[] buffer = new byte[count];
|
||||
int offset = 0;
|
||||
|
||||
while (offset < count)
|
||||
{
|
||||
int bytesRead = stream.Read(buffer, offset, count - offset);
|
||||
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
offset += bytesRead;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace AppDiagnostic.Logging
|
||||
{
|
||||
public static class DiagnosticProtocol
|
||||
{
|
||||
public const string DefaultPipeName = "Sensus.AppDiagnostic.LogPipe";
|
||||
public const int MaximumMessageSize = 1024 * 1024;
|
||||
public const int DefaultQueueLimit = 10000;
|
||||
public const int DefaultReconnectDelayMilliseconds = 500;
|
||||
public const int DefaultConnectTimeoutMilliseconds = 250;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# AppDiagnostic.Logging
|
||||
|
||||
Reusable NLog target for sending structured diagnostic events from multiple
|
||||
.NET Framework processes to `AppDiagnostic.exe` through a local named pipe.
|
||||
|
||||
## Producer integration
|
||||
|
||||
Reference this project from the producer application and add the extension and
|
||||
target to its NLog configuration:
|
||||
|
||||
```xml
|
||||
<extensions>
|
||||
<add assembly="AppDiagnostic.Logging" />
|
||||
</extensions>
|
||||
|
||||
<targets>
|
||||
<target name="appDiagnostic"
|
||||
xsi:type="AppDiagnostic"
|
||||
layout="${message}" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="*" minlevel="Trace" writeTo="appDiagnostic" />
|
||||
</rules>
|
||||
```
|
||||
|
||||
The target writes to a bounded background queue. Producer threads are not
|
||||
blocked while the diagnostic viewer is unavailable. Queued messages are sent
|
||||
after the viewer becomes available; new messages are discarded when the queue
|
||||
limit is reached.
|
||||
|
||||
The receiver can read messages with:
|
||||
|
||||
```csharp
|
||||
DiagnosticLogEntry entry =
|
||||
DiagnosticMessageSerializer.ReadFramed(namedPipeServerStream);
|
||||
```
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj",
|
||||
"projectName": "AppDiagnostic.Logging",
|
||||
"projectPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj",
|
||||
"packagesPath": "C:\\Users\\MFRNIAK\\.nuget\\packages\\",
|
||||
"outputPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\MFRNIAK\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net472"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net472": {
|
||||
"framework": "net472",
|
||||
"targetAlias": "net472",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net472": {
|
||||
"framework": "net472",
|
||||
"targetAlias": "net472",
|
||||
"dependencies": {
|
||||
"NLog": {
|
||||
"target": "Package",
|
||||
"version": "[5.2.2, )"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.303\\RuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\MFRNIAK\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\MFRNIAK\.nuget\packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
is_global = true
|
||||
build_property.RootNamespace = AppDiagnostic.Logging
|
||||
build_property.ProjectDir = C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.CsWinRTUseWindowsUIXamlProjections = false
|
||||
build_property.EffectiveAnalysisLevelStyle =
|
||||
build_property.EnableCodeStyleSeverity =
|
||||
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
551ba94934db30a277a1a9cec2dacbe03f8393107e5d0b2436695f9bd62bd569
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\AppDiagnostic.Logging.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\AppDiagnostic.Logging.pdb
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\NLog.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.csproj.AssemblyReference.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.AssemblyInfoInputs.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.AssemblyInfo.cs
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.csproj.CoreCompileInputs.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagn.CFEA7AC0.Up2Date
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.pdb
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
is_global = true
|
||||
build_property.RootNamespace = AppDiagnostic.Logging
|
||||
build_property.ProjectDir = C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.CsWinRTUseWindowsUIXamlProjections = false
|
||||
build_property.EffectiveAnalysisLevelStyle =
|
||||
build_property.EnableCodeStyleSeverity =
|
||||
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
a53d59482cad49b656138b1af5cf3e55edf2108969aedc574c362be6c671436b
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\AppDiagnostic.Logging.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\AppDiagnostic.Logging.pdb
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\NLog.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.csproj.AssemblyReference.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.AssemblyInfoInputs.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.AssemblyInfo.cs
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.csproj.CoreCompileInputs.cache
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagn.CFEA7AC0.Up2Date
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.dll
|
||||
C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.pdb
|
||||
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"version": 4,
|
||||
"targets": {
|
||||
"net472": {
|
||||
"NLog/5.2.2": {
|
||||
"type": "package",
|
||||
"frameworkAssemblies": [
|
||||
"System",
|
||||
"System.Configuration",
|
||||
"System.Core",
|
||||
"System.IO.Compression",
|
||||
"System.Xml"
|
||||
],
|
||||
"compile": {
|
||||
"lib/net46/NLog.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net46/NLog.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"NLog/5.2.2": {
|
||||
"sha512": "r6Q9740g29gTwmTWlsgdIFm0mhNsfNZmbvWKX/Fxmi8X89ZrpUowHM2T2X1lP7RVpND+ef+XnfKL5g6Q1iNGXA==",
|
||||
"type": "package",
|
||||
"path": "nlog/5.2.2",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"N.png",
|
||||
"lib/net35/NLog.dll",
|
||||
"lib/net35/NLog.xml",
|
||||
"lib/net45/NLog.dll",
|
||||
"lib/net45/NLog.xml",
|
||||
"lib/net46/NLog.dll",
|
||||
"lib/net46/NLog.xml",
|
||||
"lib/netstandard1.3/NLog.dll",
|
||||
"lib/netstandard1.3/NLog.xml",
|
||||
"lib/netstandard1.5/NLog.dll",
|
||||
"lib/netstandard1.5/NLog.xml",
|
||||
"lib/netstandard2.0/NLog.dll",
|
||||
"lib/netstandard2.0/NLog.xml",
|
||||
"nlog.5.2.2.nupkg.sha512",
|
||||
"nlog.nuspec"
|
||||
]
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
"net472": [
|
||||
"NLog >= 5.2.2"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"C:\\Users\\MFRNIAK\\.nuget\\packages\\": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj",
|
||||
"projectName": "AppDiagnostic.Logging",
|
||||
"projectPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj",
|
||||
"packagesPath": "C:\\Users\\MFRNIAK\\.nuget\\packages\\",
|
||||
"outputPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\MFRNIAK\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net472"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net472": {
|
||||
"framework": "net472",
|
||||
"targetAlias": "net472",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.300"
|
||||
},
|
||||
"frameworks": {
|
||||
"net472": {
|
||||
"framework": "net472",
|
||||
"targetAlias": "net472",
|
||||
"dependencies": {
|
||||
"NLog": {
|
||||
"target": "Package",
|
||||
"version": "[5.2.2, )"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.303\\RuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "ezwKOPZAAXU=",
|
||||
"success": true,
|
||||
"projectFilePath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\MFRNIAK\\.nuget\\packages\\nlog\\5.2.2\\nlog.5.2.2.nupkg.sha512"
|
||||
],
|
||||
"logs": []
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>AppDiagnostic</RootNamespace>
|
||||
<AssemblyName>AppDiagnostic</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ColorRuleEditorForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DiagnosticLogFormatter.cs" />
|
||||
<Compile Include="DiagnosticLogStore.cs" />
|
||||
<Compile Include="DiagnosticPipeServer.cs" />
|
||||
<Compile Include="LogColorizer.cs" />
|
||||
<Compile Include="LogColorRule.cs" />
|
||||
<Compile Include="LogColorRuleRepository.cs" />
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.Designer.cs">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AppDiagnostic.Logging\AppDiagnostic.Logging.csproj">
|
||||
<Project>{A7AF8ED2-362E-4DBB-B607-EBA2820719EC}</Project>
|
||||
<Name>AppDiagnostic.Logging</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\TBF_icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
public class BufferedListView : ListView
|
||||
{
|
||||
public BufferedListView()
|
||||
{
|
||||
// Zapne dvojité bufferovanie pre ListView
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.UpdateStyles();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public sealed class ColorRuleEditorForm : Form
|
||||
{
|
||||
private readonly List<LogColorRule> rules;
|
||||
private readonly ListBox ruleList = new ListBox();
|
||||
private readonly TextBox patternTextBox = new TextBox();
|
||||
private readonly CheckBox enabledCheckBox = new CheckBox();
|
||||
private readonly CheckBox boldCheckBox = new CheckBox();
|
||||
private readonly CheckBox backgroundCheckBox = new CheckBox();
|
||||
private readonly Button foregroundButton = new Button();
|
||||
private readonly Button backgroundButton = new Button();
|
||||
private readonly RichTextBox previewBox = new RichTextBox();
|
||||
private readonly Font previewBoldFont;
|
||||
private bool loadingRule;
|
||||
|
||||
public ColorRuleEditorForm(IEnumerable<LogColorRule> sourceRules)
|
||||
{
|
||||
rules = sourceRules.Select(rule => rule.Clone()).ToList();
|
||||
InitializeWindow();
|
||||
previewBoldFont = new Font(previewBox.Font, FontStyle.Bold);
|
||||
RefreshRuleList(0);
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
public List<LogColorRule> Rules => rules.Select(rule => rule.Clone()).ToList();
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
previewBoldFont.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void InitializeWindow()
|
||||
{
|
||||
Text = "Log color rules";
|
||||
Icon = Properties.Resources.TBF_icon;
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
MinimumSize = new Size(760, 500);
|
||||
ClientSize = new Size(860, 560);
|
||||
|
||||
var root = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 1, RowCount = 3, Padding = new Padding(10) };
|
||||
root.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 145F));
|
||||
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 42F));
|
||||
|
||||
var split = new SplitContainer { Dock = DockStyle.Fill, SplitterDistance = 280 };
|
||||
split.Panel1.Padding = new Padding(0, 0, 8, 0);
|
||||
split.Panel2.Padding = new Padding(8, 0, 0, 0);
|
||||
|
||||
ruleList.Dock = DockStyle.Fill;
|
||||
ruleList.IntegralHeight = false;
|
||||
ruleList.SelectedIndexChanged += RuleList_SelectedIndexChanged;
|
||||
|
||||
var listButtons = new FlowLayoutPanel { Dock = DockStyle.Bottom, Height = 36, FlowDirection = FlowDirection.LeftToRight };
|
||||
listButtons.Controls.Add(CreateButton("Add", AddRule_Click));
|
||||
listButtons.Controls.Add(CreateButton("Delete", DeleteRule_Click));
|
||||
listButtons.Controls.Add(CreateButton("Up", MoveUp_Click));
|
||||
listButtons.Controls.Add(CreateButton("Down", MoveDown_Click));
|
||||
split.Panel1.Controls.Add(ruleList);
|
||||
split.Panel1.Controls.Add(listButtons);
|
||||
|
||||
var editor = new TableLayoutPanel { Dock = DockStyle.Top, AutoSize = true, ColumnCount = 2, Padding = new Padding(4) };
|
||||
editor.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F));
|
||||
editor.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||
|
||||
enabledCheckBox.Text = "Rule enabled";
|
||||
enabledCheckBox.AutoSize = true;
|
||||
enabledCheckBox.CheckedChanged += EditorValueChanged;
|
||||
AddEditorRow(editor, "State", enabledCheckBox);
|
||||
|
||||
patternTextBox.Dock = DockStyle.Fill;
|
||||
patternTextBox.TextChanged += EditorValueChanged;
|
||||
AddEditorRow(editor, "Substring", patternTextBox);
|
||||
|
||||
foregroundButton.Text = "Choose text color...";
|
||||
foregroundButton.AutoSize = true;
|
||||
foregroundButton.Click += ForegroundButton_Click;
|
||||
AddEditorRow(editor, "Text color", foregroundButton);
|
||||
|
||||
var backgroundPanel = new FlowLayoutPanel { Dock = DockStyle.Fill, AutoSize = true };
|
||||
backgroundCheckBox.Text = "Use background";
|
||||
backgroundCheckBox.AutoSize = true;
|
||||
backgroundCheckBox.CheckedChanged += EditorValueChanged;
|
||||
backgroundButton.Text = "Choose...";
|
||||
backgroundButton.AutoSize = true;
|
||||
backgroundButton.Click += BackgroundButton_Click;
|
||||
backgroundPanel.Controls.Add(backgroundCheckBox);
|
||||
backgroundPanel.Controls.Add(backgroundButton);
|
||||
AddEditorRow(editor, "Background", backgroundPanel);
|
||||
|
||||
boldCheckBox.Text = "Bold text";
|
||||
boldCheckBox.AutoSize = true;
|
||||
boldCheckBox.CheckedChanged += EditorValueChanged;
|
||||
AddEditorRow(editor, "Font", boldCheckBox);
|
||||
|
||||
var resetButton = CreateButton("Restore default rules", RestoreDefaults_Click);
|
||||
resetButton.AutoSize = true;
|
||||
AddEditorRow(editor, string.Empty, resetButton);
|
||||
split.Panel2.Controls.Add(editor);
|
||||
|
||||
previewBox.Dock = DockStyle.Fill;
|
||||
previewBox.ReadOnly = true;
|
||||
previewBox.WordWrap = true;
|
||||
previewBox.Font = new Font("Consolas", 9F);
|
||||
previewBox.Text = "2026-09-10 14:25:31.042|DEBUG|TBF[14280]|TBF.UI.MainWnd|Device configuration loaded.\n2026-09-10 14:25:31.384|INFO |TBF[14280]|TBF.Rig.StateMachine|Test bench started.\n2026-09-10 14:25:32.018|WARN |TBF[14280]|TBF.Device|Pressure is approaching the limit.\n2026-09-10 14:25:32.611|ERROR|TBF[14280]|TBF.Device|Communication failed.";
|
||||
|
||||
var previewGroup = new GroupBox { Text = "Live preview", Dock = DockStyle.Fill, Padding = new Padding(8) };
|
||||
previewGroup.Controls.Add(previewBox);
|
||||
|
||||
var footer = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.RightToLeft, Padding = new Padding(0, 8, 0, 0) };
|
||||
var okButton = new Button { Text = "OK", DialogResult = DialogResult.OK, AutoSize = true };
|
||||
var cancelButton = new Button { Text = "Cancel", DialogResult = DialogResult.Cancel, AutoSize = true };
|
||||
footer.Controls.Add(okButton);
|
||||
footer.Controls.Add(cancelButton);
|
||||
|
||||
AcceptButton = okButton;
|
||||
CancelButton = cancelButton;
|
||||
root.Controls.Add(split, 0, 0);
|
||||
root.Controls.Add(previewGroup, 0, 1);
|
||||
root.Controls.Add(footer, 0, 2);
|
||||
Controls.Add(root);
|
||||
}
|
||||
|
||||
private static Button CreateButton(string text, EventHandler clickHandler)
|
||||
{
|
||||
var button = new Button { Text = text, AutoSize = true };
|
||||
button.Click += clickHandler;
|
||||
return button;
|
||||
}
|
||||
|
||||
private static void AddEditorRow(TableLayoutPanel panel, string labelText, Control control)
|
||||
{
|
||||
int row = panel.RowCount++;
|
||||
panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||||
var label = new Label { Text = labelText, AutoSize = true, Anchor = AnchorStyles.Left, Margin = new Padding(3, 8, 3, 3) };
|
||||
control.Margin = new Padding(3, 5, 3, 5);
|
||||
panel.Controls.Add(label, 0, row);
|
||||
panel.Controls.Add(control, 1, row);
|
||||
}
|
||||
|
||||
private void RefreshRuleList(int selectedIndex)
|
||||
{
|
||||
ruleList.BeginUpdate();
|
||||
ruleList.Items.Clear();
|
||||
foreach (LogColorRule rule in rules)
|
||||
{
|
||||
ruleList.Items.Add(rule);
|
||||
}
|
||||
ruleList.EndUpdate();
|
||||
|
||||
if (rules.Count > 0)
|
||||
{
|
||||
ruleList.SelectedIndex = Math.Max(0, Math.Min(selectedIndex, rules.Count - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void RuleList_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
LogColorRule rule = ruleList.SelectedItem as LogColorRule;
|
||||
if (rule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
loadingRule = true;
|
||||
enabledCheckBox.Checked = rule.Enabled;
|
||||
patternTextBox.Text = rule.Pattern;
|
||||
foregroundButton.BackColor = rule.ForeColor;
|
||||
backgroundCheckBox.Checked = rule.UseBackColor;
|
||||
backgroundButton.Enabled = rule.UseBackColor;
|
||||
backgroundButton.BackColor = rule.UseBackColor ? rule.BackColor : SystemColors.Control;
|
||||
boldCheckBox.Checked = rule.Bold;
|
||||
loadingRule = false;
|
||||
}
|
||||
|
||||
private void EditorValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (loadingRule)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogColorRule rule = ruleList.SelectedItem as LogColorRule;
|
||||
if (rule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rule.Enabled = enabledCheckBox.Checked;
|
||||
rule.Pattern = patternTextBox.Text;
|
||||
rule.UseBackColor = backgroundCheckBox.Checked;
|
||||
rule.Bold = boldCheckBox.Checked;
|
||||
backgroundButton.Enabled = rule.UseBackColor;
|
||||
int index = ruleList.SelectedIndex;
|
||||
RefreshRuleList(index);
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
private void ForegroundButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
LogColorRule rule = ruleList.SelectedItem as LogColorRule;
|
||||
if (rule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var dialog = new ColorDialog { Color = rule.ForeColor, FullOpen = true })
|
||||
{
|
||||
if (dialog.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rule.ForeColorArgb = dialog.Color.ToArgb();
|
||||
foregroundButton.BackColor = dialog.Color;
|
||||
RefreshPreview();
|
||||
}
|
||||
}
|
||||
|
||||
private void BackgroundButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
LogColorRule rule = ruleList.SelectedItem as LogColorRule;
|
||||
if (rule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Color initialColor = rule.UseBackColor ? rule.BackColor : SystemColors.Window;
|
||||
using (var dialog = new ColorDialog { Color = initialColor, FullOpen = true })
|
||||
{
|
||||
if (dialog.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rule.BackColorArgb = dialog.Color.ToArgb();
|
||||
rule.UseBackColor = true;
|
||||
backgroundCheckBox.Checked = true;
|
||||
backgroundButton.BackColor = dialog.Color;
|
||||
RefreshPreview();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRule_Click(object sender, EventArgs e)
|
||||
{
|
||||
rules.Add(new LogColorRule { Pattern = "NEW SUBSTRING", ForeColorArgb = Color.MediumPurple.ToArgb() });
|
||||
RefreshRuleList(rules.Count - 1);
|
||||
patternTextBox.Focus();
|
||||
patternTextBox.SelectAll();
|
||||
}
|
||||
|
||||
private void DeleteRule_Click(object sender, EventArgs e)
|
||||
{
|
||||
int index = ruleList.SelectedIndex;
|
||||
if (index < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rules.RemoveAt(index);
|
||||
RefreshRuleList(Math.Min(index, rules.Count - 1));
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
private void MoveUp_Click(object sender, EventArgs e)
|
||||
{
|
||||
MoveSelectedRule(-1);
|
||||
}
|
||||
|
||||
private void MoveDown_Click(object sender, EventArgs e)
|
||||
{
|
||||
MoveSelectedRule(1);
|
||||
}
|
||||
|
||||
private void MoveSelectedRule(int offset)
|
||||
{
|
||||
int index = ruleList.SelectedIndex;
|
||||
int newIndex = index + offset;
|
||||
if (index < 0 || newIndex < 0 || newIndex >= rules.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogColorRule rule = rules[index];
|
||||
rules.RemoveAt(index);
|
||||
rules.Insert(newIndex, rule);
|
||||
RefreshRuleList(newIndex);
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
private void RestoreDefaults_Click(object sender, EventArgs e)
|
||||
{
|
||||
rules.Clear();
|
||||
rules.AddRange(LogColorRule.CreateDefaults());
|
||||
RefreshRuleList(0);
|
||||
RefreshPreview();
|
||||
}
|
||||
|
||||
private void RefreshPreview()
|
||||
{
|
||||
int selectionStart = previewBox.SelectionStart;
|
||||
int selectionLength = previewBox.SelectionLength;
|
||||
string text = previewBox.Text;
|
||||
LogColorizer.Apply(previewBox, 0, text.Length, text, rules, previewBox.Font, previewBoldFont);
|
||||
previewBox.Select(Math.Min(selectionStart, previewBox.TextLength), Math.Min(selectionLength, Math.Max(0, previewBox.TextLength - selectionStart)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public class DiagApi
|
||||
{
|
||||
private static MainForm diagWindow; // Udržiava referenciu na existujúce okno
|
||||
|
||||
public DiagApi()
|
||||
{
|
||||
if (diagWindow == null || diagWindow.IsDisposed) // Ak okno neexistuje, vytvoríme ho
|
||||
{
|
||||
diagWindow = new MainForm();
|
||||
diagWindow.FormClosing += (s, e) =>
|
||||
{
|
||||
diagWindow = null; // Keď sa zavrie, vyčistíme referenciu
|
||||
};
|
||||
diagWindow.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
diagWindow.BringToFront(); // Ak už beží, len ho presunieme na vrch
|
||||
diagWindow.WindowState = FormWindowState.Normal; // Ak je minimalizované, obnovíme ho
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using AppDiagnostic.Logging;
|
||||
using System;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public static class DiagnosticLogFormatter
|
||||
{
|
||||
public static string Format(DiagnosticLogEntry entry)
|
||||
{
|
||||
if (entry == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string level = (entry.Level ?? string.Empty).ToUpperInvariant().PadRight(5);
|
||||
string application = string.IsNullOrWhiteSpace(entry.ApplicationName) ? "Unknown" : entry.ApplicationName;
|
||||
string logger = entry.LoggerName ?? string.Empty;
|
||||
string message = entry.Message ?? string.Empty;
|
||||
string exception = string.IsNullOrWhiteSpace(entry.Exception) ? string.Empty : Environment.NewLine + entry.Exception;
|
||||
|
||||
return $"{entry.TimestampUtc.ToLocalTime():yyyy-MM-dd HH:mm:ss.fff}|{level}|{application}[{entry.ProcessId}]|{logger}|{message}{exception}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using AppDiagnostic.Logging;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public sealed class DiagnosticLogStore
|
||||
{
|
||||
private const int MaximumLogCount = 10000;
|
||||
private static readonly DiagnosticLogStore instance = new DiagnosticLogStore();
|
||||
private readonly object syncRoot = new object();
|
||||
private readonly List<DiagnosticLogEntry> entries = new List<DiagnosticLogEntry>();
|
||||
private long totalReceived;
|
||||
private long version;
|
||||
|
||||
private DiagnosticLogStore()
|
||||
{
|
||||
}
|
||||
|
||||
public static DiagnosticLogStore Instance => instance;
|
||||
|
||||
public long TotalReceived
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
return totalReceived;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long Version
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(DiagnosticLogEntry entry)
|
||||
{
|
||||
if (entry == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
entries.Add(entry);
|
||||
totalReceived++;
|
||||
version++;
|
||||
|
||||
int excessCount = entries.Count - MaximumLogCount;
|
||||
if (excessCount > 0)
|
||||
{
|
||||
entries.RemoveRange(0, excessCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<DiagnosticLogEntry> GetSnapshot()
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
return entries.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
entries.Clear();
|
||||
version++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using AppDiagnostic.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public sealed class DiagnosticPipeServer : IDisposable
|
||||
{
|
||||
private readonly Action<DiagnosticLogEntry> messageReceived;
|
||||
private readonly CancellationTokenSource cancellation = new CancellationTokenSource();
|
||||
private readonly object syncRoot = new object();
|
||||
private readonly List<NamedPipeServerStream> connectedClients = new List<NamedPipeServerStream>();
|
||||
private NamedPipeServerStream waitingServer;
|
||||
private Task serverTask;
|
||||
|
||||
public DiagnosticPipeServer(Action<DiagnosticLogEntry> messageReceived)
|
||||
{
|
||||
this.messageReceived = messageReceived ?? throw new ArgumentNullException(nameof(messageReceived));
|
||||
}
|
||||
|
||||
public int ConnectedClientCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
return connectedClients.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (serverTask != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
serverTask = Task.Run((Action)AcceptConnections);
|
||||
}
|
||||
|
||||
private void AcceptConnections()
|
||||
{
|
||||
while (!cancellation.IsCancellationRequested)
|
||||
{
|
||||
NamedPipeServerStream server = null;
|
||||
|
||||
try
|
||||
{
|
||||
server = new NamedPipeServerStream(DiagnosticProtocol.DefaultPipeName, PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
waitingServer = server;
|
||||
}
|
||||
|
||||
server.WaitForConnection();
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
waitingServer = null;
|
||||
connectedClients.Add(server);
|
||||
}
|
||||
|
||||
NamedPipeServerStream connectedServer = server;
|
||||
server = null;
|
||||
Task.Run(() => ReadClient(connectedServer));
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
if (!cancellation.IsCancellationRequested)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
if (!cancellation.IsCancellationRequested)
|
||||
{
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
if (ReferenceEquals(waitingServer, server))
|
||||
{
|
||||
waitingServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
server?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadClient(NamedPipeServerStream client)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (client.IsConnected && !cancellation.IsCancellationRequested)
|
||||
{
|
||||
DiagnosticLogEntry entry = DiagnosticMessageSerializer.ReadFramed(client);
|
||||
messageReceived(entry);
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
// The producer application was closed.
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// The producer application disconnected.
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// The diagnostic application is shutting down.
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
connectedClients.Remove(client);
|
||||
}
|
||||
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
cancellation.Cancel();
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
waitingServer?.Dispose();
|
||||
waitingServer = null;
|
||||
|
||||
foreach (NamedPipeServerStream client in connectedClients.ToArray())
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
|
||||
connectedClients.Clear();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
serverTask?.Wait(2000);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
// Cancellation during shutdown is expected.
|
||||
}
|
||||
|
||||
cancellation.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using SharedComponents;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public class LogAdapter
|
||||
{
|
||||
private ListView _listView;
|
||||
public string _filterText = string.Empty;
|
||||
private bool _isUserScrolling = false; // Indikátor, že používateľ manuálne scrolluje
|
||||
private bool _autoScrollEnabled = true; // Indikátor, že automatické scrollovanie je povolené
|
||||
private Timer _refreshTimer;
|
||||
private const int RefreshInterval = 1000;
|
||||
|
||||
public LogAdapter(ListView listView)
|
||||
{
|
||||
_listView = listView;
|
||||
|
||||
// Nastavenie ListView
|
||||
_listView.View = View.Details;
|
||||
_listView.Columns.Clear();
|
||||
_listView.Columns.Add("Logs");
|
||||
|
||||
_listView.Scrollable = true;
|
||||
|
||||
// Nastavenie šírky stĺpca na celú šírku ListView
|
||||
AdjustColumnWidth();
|
||||
|
||||
// Udalosť pre dynamickú zmenu veľkosti stĺpca pri zmene veľkosti ListView
|
||||
_listView.Resize += (sender, args) => AdjustColumnWidth();
|
||||
|
||||
// Pridanie udalosti pre manuálne skrolovanie
|
||||
_listView.MouseWheel += ListView_MouseWheel;
|
||||
|
||||
// Inicializácia časovača na pravidelný refresh
|
||||
_refreshTimer = new Timer { Interval = RefreshInterval };
|
||||
_refreshTimer.Tick += (sender, args) => RefreshListView();
|
||||
_refreshTimer.Start();
|
||||
}
|
||||
|
||||
private void ListView_MouseWheel(object sender, MouseEventArgs e)
|
||||
{
|
||||
_isUserScrolling = true;
|
||||
|
||||
// Ak sa manuálnym scrollovaním používateľ dostane na koniec, obnovíme automatické scrollovanie
|
||||
if (IsOnLastItem())
|
||||
{
|
||||
_isUserScrolling = false;
|
||||
_autoScrollEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_autoScrollEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshListView()
|
||||
{
|
||||
//LiveLogCache.Instance.AddLog(string.Format("-------------------------------RunDeviceAfter()-------------------------------"));
|
||||
|
||||
if (_listView.InvokeRequired)
|
||||
{
|
||||
_listView.Invoke(new Action(RefreshListView));
|
||||
return;
|
||||
}
|
||||
|
||||
_listView.BeginUpdate();
|
||||
try
|
||||
{
|
||||
// Získanie pozície prvého viditeľného prvku pre stabilizáciu scrollovania
|
||||
int topIndexBeforeRefresh = _listView.TopItem?.Index ?? 0;
|
||||
|
||||
// Pred pridaním nových položiek si pamätáme, či bol používateľ na poslednej položke
|
||||
bool wasOnLastItem = IsOnLastItem();
|
||||
|
||||
// Uchovanie aktuálne označených položiek (indexov)
|
||||
var selectedIndices = _listView.SelectedIndices.Cast<int>().ToList();
|
||||
|
||||
// Načítanie logov
|
||||
var logs = LiveLogCache.Instance.GetLogs(0, LiveLogCache.Instance.GetCount())
|
||||
.Where(log => string.IsNullOrEmpty(_filterText) ||
|
||||
log.IndexOf(_filterText, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
.ToList();
|
||||
|
||||
// Vymazanie existujúcich položiek a pridanie nových
|
||||
_listView.Items.Clear();
|
||||
|
||||
foreach (var log in logs)
|
||||
{
|
||||
var item = new ListViewItem(log)
|
||||
{
|
||||
BackColor = _listView.Items.Count % 2 == 0 ? Color.White : Color.FromArgb(240, 240, 240)
|
||||
};
|
||||
_listView.Items.Add(item);
|
||||
}
|
||||
|
||||
// Obnovenie označených položiek
|
||||
foreach (var index in selectedIndices)
|
||||
{
|
||||
if (index < _listView.Items.Count)
|
||||
{
|
||||
_listView.Items[index].Selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ak bol používateľ na poslednom prvku, nastavíme focus a scroll na posledný prvok
|
||||
if (_autoScrollEnabled && wasOnLastItem && _listView.Items.Count > 0)
|
||||
{
|
||||
var lastItemIndex = _listView.Items.Count - 1;
|
||||
_listView.EnsureVisible(lastItemIndex);
|
||||
_listView.Items[lastItemIndex].Focused = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ak používateľ nebol na spodku, vrátime sa na predchádzajúcu pozíciu scrollu
|
||||
if (topIndexBeforeRefresh < _listView.Items.Count)
|
||||
{
|
||||
_listView.TopItem = _listView.Items[topIndexBeforeRefresh];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_listView.EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ApplyFilter(string filterText)
|
||||
{
|
||||
_filterText = filterText?.Trim() ?? string.Empty;
|
||||
RefreshListView();
|
||||
}
|
||||
|
||||
private bool IsOnLastItem()
|
||||
{
|
||||
if (_listView.Items.Count == 0)
|
||||
return false;
|
||||
|
||||
// Získame poslednú položku
|
||||
int lastItemIndex = _listView.Items.Count - 1;
|
||||
var lastItem = _listView.Items[lastItemIndex];
|
||||
|
||||
// Overíme, či je posledná položka úplne viditeľná
|
||||
return lastItem.Bounds.Bottom <= _listView.ClientRectangle.Bottom;
|
||||
}
|
||||
|
||||
public void EnableAutoScroll()
|
||||
{
|
||||
_autoScrollEnabled = true;
|
||||
}
|
||||
|
||||
public void DisableAutoScroll()
|
||||
{
|
||||
_autoScrollEnabled = false;
|
||||
}
|
||||
|
||||
private void AdjustColumnWidth()
|
||||
{
|
||||
if (_listView.Columns.Count > 0)
|
||||
{
|
||||
_listView.Columns[0].Width = _listView.ClientSize.Width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class LogColorRule
|
||||
{
|
||||
public bool Enabled { get; set; } = true;
|
||||
public string Pattern { get; set; } = string.Empty;
|
||||
public int ForeColorArgb { get; set; } = Color.Black.ToArgb();
|
||||
public int BackColorArgb { get; set; }
|
||||
public bool UseBackColor { get; set; }
|
||||
public bool Bold { get; set; }
|
||||
|
||||
public Color ForeColor => Color.FromArgb(ForeColorArgb);
|
||||
public Color BackColor => Color.FromArgb(BackColorArgb);
|
||||
|
||||
public LogColorRule Clone()
|
||||
{
|
||||
return new LogColorRule
|
||||
{
|
||||
Enabled = Enabled,
|
||||
Pattern = Pattern,
|
||||
ForeColorArgb = ForeColorArgb,
|
||||
BackColorArgb = BackColorArgb,
|
||||
UseBackColor = UseBackColor,
|
||||
Bold = Bold
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string state = Enabled ? string.Empty : "[disabled] ";
|
||||
return state + Pattern;
|
||||
}
|
||||
|
||||
public static List<LogColorRule> CreateDefaults()
|
||||
{
|
||||
return new List<LogColorRule>
|
||||
{
|
||||
Create("|TRACE|", Color.DimGray, false),
|
||||
Create("|DEBUG|", Color.RoyalBlue, false),
|
||||
Create("|INFO |", Color.ForestGreen, false),
|
||||
Create("|WARN |", Color.DarkOrange, true),
|
||||
Create("|ERROR|", Color.Crimson, true),
|
||||
Create("|FATAL|", Color.White, true, Color.DarkRed)
|
||||
};
|
||||
}
|
||||
|
||||
private static LogColorRule Create(string pattern, Color foreground, bool bold, Color? background = null)
|
||||
{
|
||||
return new LogColorRule
|
||||
{
|
||||
Enabled = true,
|
||||
Pattern = pattern,
|
||||
ForeColorArgb = foreground.ToArgb(),
|
||||
BackColorArgb = background?.ToArgb() ?? Color.Empty.ToArgb(),
|
||||
UseBackColor = background.HasValue,
|
||||
Bold = bold
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public static class LogColorRuleRepository
|
||||
{
|
||||
private static readonly string settingsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Sensus", "AppDiagnostic");
|
||||
private static readonly string settingsPath = Path.Combine(settingsFolder, "color-rules.xml");
|
||||
|
||||
public static List<LogColorRule> Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
return LogColorRule.CreateDefaults();
|
||||
}
|
||||
|
||||
var serializer = new XmlSerializer(typeof(List<LogColorRule>));
|
||||
using (FileStream stream = File.OpenRead(settingsPath))
|
||||
{
|
||||
var rules = serializer.Deserialize(stream) as List<LogColorRule>;
|
||||
return rules == null || rules.Count == 0 ? LogColorRule.CreateDefaults() : rules;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return LogColorRule.CreateDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save(IEnumerable<LogColorRule> rules)
|
||||
{
|
||||
Directory.CreateDirectory(settingsFolder);
|
||||
|
||||
var serializer = new XmlSerializer(typeof(List<LogColorRule>));
|
||||
using (FileStream stream = File.Create(settingsPath))
|
||||
{
|
||||
serializer.Serialize(stream, new List<LogColorRule>(rules));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public static class LogColorizer
|
||||
{
|
||||
public static void Apply(RichTextBox target, int startIndex, int length, string text, IEnumerable<LogColorRule> rules, Font regularFont, Font boldFont)
|
||||
{
|
||||
if (target == null || length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
target.Select(startIndex, length);
|
||||
target.SelectionColor = target.ForeColor;
|
||||
target.SelectionBackColor = target.BackColor;
|
||||
target.SelectionFont = regularFont;
|
||||
|
||||
foreach (LogColorRule rule in rules)
|
||||
{
|
||||
if (rule == null || !rule.Enabled || string.IsNullOrEmpty(rule.Pattern))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int searchIndex = 0;
|
||||
while (searchIndex < text.Length)
|
||||
{
|
||||
int matchIndex = text.IndexOf(rule.Pattern, searchIndex, StringComparison.OrdinalIgnoreCase);
|
||||
if (matchIndex < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
target.Select(startIndex + matchIndex, rule.Pattern.Length);
|
||||
target.SelectionColor = rule.ForeColor;
|
||||
target.SelectionBackColor = rule.UseBackColor ? rule.BackColor : target.BackColor;
|
||||
target.SelectionFont = rule.Bold ? boldFont : regularFont;
|
||||
searchIndex = matchIndex + rule.Pattern.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using SharedComponents;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public class LogFilter
|
||||
{
|
||||
private ListView _listView;
|
||||
private string _filterText = string.Empty; // Pre uloženie aktuálneho filtrovaného reťazca
|
||||
|
||||
// Konstruktor
|
||||
public LogFilter(ListView listView)
|
||||
{
|
||||
_listView = listView;
|
||||
}
|
||||
|
||||
// Metóda na aplikovanie filtra na ListView
|
||||
public void ApplyFilter(string filterText)
|
||||
{
|
||||
_filterText = filterText.ToLower(); // Ukladáme text filtra bez ohľadu na veľkosť písmen
|
||||
|
||||
// Po aplikovaní filtra obnovíme zobrazenie
|
||||
RefreshListView();
|
||||
}
|
||||
|
||||
public void RefreshListView()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Skontrolujeme, či sme na hlavnom vlákne a v prípade potreby použijeme Invoke
|
||||
if (_listView.InvokeRequired)
|
||||
{
|
||||
// Použijeme Invoke, ak nie sme na hlavnom vlákne
|
||||
_listView.Invoke(new Action(RefreshListView));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Vymazanie existujúcich položiek
|
||||
_listView.Items.Clear();
|
||||
|
||||
// Načítame všetky logy (ideálne z cache alebo databázy)
|
||||
var logs = LiveLogCache.Instance.GetLogs(0, LiveLogCache.Instance.Logs.Count);
|
||||
|
||||
// Pridáme len tie logy, ktoré spĺňajú filter
|
||||
foreach (var log in logs)
|
||||
{
|
||||
if (log.ToLower().Contains(_filterText)) // Kontrola, či log obsahuje filter text
|
||||
{
|
||||
var listViewItem = new ListViewItem(log);
|
||||
|
||||
// Striedanie farieb riadkov
|
||||
if (_listView.Items.Count % 2 == 0) // Párny index => biela
|
||||
{
|
||||
listViewItem.BackColor = Color.White;
|
||||
}
|
||||
else // Nepárny index => svetlá sivá
|
||||
{
|
||||
listViewItem.BackColor = Color.FromArgb(240, 240, 240); // Veľmi svetlá sivá
|
||||
}
|
||||
|
||||
// Pridanie efektu pre novú položku
|
||||
ApplyNewItemEffect(listViewItem);
|
||||
|
||||
// Pridanie položky do ListView
|
||||
_listView.Items.Add(listViewItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Zachytíme výnimku, ak sa niečo pokazí, a zobrazíme ju užívateľovi
|
||||
MessageBox.Show($"An error occurred while refreshing the log view: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// Môžete pridať ďalšie metódy na zobrazenie alebo efekt pre nové položky, ak je to potrebné
|
||||
private void ApplyNewItemEffect(ListViewItem item)
|
||||
{
|
||||
// Prípadný efekt pre nový pridaný log
|
||||
// Môžete pridať animáciu alebo zmenu farby atď.
|
||||
item.ForeColor = Color.Green; // Napríklad zmeníme farbu písma na zelenú
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+309
@@ -0,0 +1,309 @@
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
private System.Windows.Forms.ToolStrip mainToolStrip;
|
||||
private System.Windows.Forms.ToolStripButton pauseButton;
|
||||
private System.Windows.Forms.ToolStripButton refreshButton;
|
||||
private System.Windows.Forms.ToolStripButton clearButton;
|
||||
private System.Windows.Forms.ToolStripButton saveButton;
|
||||
private System.Windows.Forms.ToolStripButton copyButton;
|
||||
private System.Windows.Forms.ToolStripButton copyAllButton;
|
||||
private System.Windows.Forms.ToolStripButton wrapButton;
|
||||
private System.Windows.Forms.ToolStripButton autoScrollButton;
|
||||
private System.Windows.Forms.ToolStripButton alwaysOnTopButton;
|
||||
private System.Windows.Forms.ToolStripButton colorRulesButton;
|
||||
private System.Windows.Forms.ToolStripButton closeButton;
|
||||
private System.Windows.Forms.TableLayoutPanel filterPanel;
|
||||
private System.Windows.Forms.Label filterLabel;
|
||||
private System.Windows.Forms.TextBox filterTextBox;
|
||||
private System.Windows.Forms.Label levelLabel;
|
||||
private System.Windows.Forms.ComboBox levelComboBox;
|
||||
private System.Windows.Forms.Label applicationLabel;
|
||||
private System.Windows.Forms.ComboBox applicationComboBox;
|
||||
private System.Windows.Forms.Button applyFilterButton;
|
||||
private System.Windows.Forms.Button clearFilterButton;
|
||||
private System.Windows.Forms.RichTextBox logView;
|
||||
private System.Windows.Forms.StatusStrip statusStrip;
|
||||
private System.Windows.Forms.ToolStripStatusLabel receiverStatusLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel statusSpacer;
|
||||
private System.Windows.Forms.ToolStripStatusLabel countStatusLabel;
|
||||
private System.Windows.Forms.ContextMenuStrip logContextMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem copySelectionMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem copyLineMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem copyAllMenuItem;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.mainToolStrip = new System.Windows.Forms.ToolStrip();
|
||||
this.pauseButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.refreshButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.clearButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.saveButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.copyButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.copyAllButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.wrapButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.autoScrollButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.alwaysOnTopButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.colorRulesButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.closeButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.filterPanel = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.filterLabel = new System.Windows.Forms.Label();
|
||||
this.filterTextBox = new System.Windows.Forms.TextBox();
|
||||
this.levelLabel = new System.Windows.Forms.Label();
|
||||
this.levelComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.applicationLabel = new System.Windows.Forms.Label();
|
||||
this.applicationComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.applyFilterButton = new System.Windows.Forms.Button();
|
||||
this.clearFilterButton = new System.Windows.Forms.Button();
|
||||
this.logContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.copySelectionMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.copyLineMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.copyAllMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.logView = new System.Windows.Forms.RichTextBox();
|
||||
this.statusStrip = new System.Windows.Forms.StatusStrip();
|
||||
this.receiverStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.statusSpacer = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.countStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.mainToolStrip.SuspendLayout();
|
||||
this.filterPanel.SuspendLayout();
|
||||
this.logContextMenu.SuspendLayout();
|
||||
this.statusStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// mainToolStrip
|
||||
//
|
||||
this.mainToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
|
||||
this.mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.pauseButton,
|
||||
this.refreshButton,
|
||||
this.clearButton,
|
||||
this.saveButton,
|
||||
new System.Windows.Forms.ToolStripSeparator(),
|
||||
this.copyButton,
|
||||
this.copyAllButton,
|
||||
new System.Windows.Forms.ToolStripSeparator(),
|
||||
this.wrapButton,
|
||||
this.autoScrollButton,
|
||||
this.alwaysOnTopButton,
|
||||
this.colorRulesButton,
|
||||
this.closeButton});
|
||||
this.mainToolStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.mainToolStrip.Name = "mainToolStrip";
|
||||
this.mainToolStrip.Padding = new System.Windows.Forms.Padding(6, 3, 6, 3);
|
||||
this.mainToolStrip.Size = new System.Drawing.Size(1184, 31);
|
||||
this.mainToolStrip.TabIndex = 0;
|
||||
//
|
||||
// pauseButton
|
||||
//
|
||||
this.pauseButton.CheckOnClick = true;
|
||||
this.pauseButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.pauseButton.Text = "Pause";
|
||||
this.pauseButton.ToolTipText = "Pause screen updates while continuing to receive logs";
|
||||
this.pauseButton.Click += new System.EventHandler(this.pauseButton_Click);
|
||||
//
|
||||
// refreshButton
|
||||
//
|
||||
this.refreshButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.refreshButton.Text = "Refresh";
|
||||
this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
|
||||
//
|
||||
// clearButton
|
||||
//
|
||||
this.clearButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.clearButton.Text = "Clear";
|
||||
this.clearButton.Click += new System.EventHandler(this.clearButton_Click);
|
||||
//
|
||||
// saveButton
|
||||
//
|
||||
this.saveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.saveButton.Text = "Save...";
|
||||
this.saveButton.Click += new System.EventHandler(this.saveButton_Click);
|
||||
//
|
||||
// copyButton
|
||||
//
|
||||
this.copyButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.copyButton.Text = "Copy";
|
||||
this.copyButton.ToolTipText = "Copy selected text or the current log line";
|
||||
this.copyButton.Click += new System.EventHandler(this.copyButton_Click);
|
||||
//
|
||||
// copyAllButton
|
||||
//
|
||||
this.copyAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.copyAllButton.Text = "Copy all";
|
||||
this.copyAllButton.Click += new System.EventHandler(this.copyAllButton_Click);
|
||||
//
|
||||
// wrapButton
|
||||
//
|
||||
this.wrapButton.Checked = true;
|
||||
this.wrapButton.CheckOnClick = true;
|
||||
this.wrapButton.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.wrapButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.wrapButton.Text = "Wrap lines";
|
||||
this.wrapButton.Click += new System.EventHandler(this.wrapButton_Click);
|
||||
//
|
||||
// autoScrollButton
|
||||
//
|
||||
this.autoScrollButton.Checked = true;
|
||||
this.autoScrollButton.CheckOnClick = true;
|
||||
this.autoScrollButton.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.autoScrollButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.autoScrollButton.Text = "Auto-scroll";
|
||||
//
|
||||
// alwaysOnTopButton
|
||||
//
|
||||
this.alwaysOnTopButton.CheckOnClick = true;
|
||||
this.alwaysOnTopButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.alwaysOnTopButton.Text = "Always on top";
|
||||
this.alwaysOnTopButton.Click += new System.EventHandler(this.alwaysOnTopButton_Click);
|
||||
//
|
||||
// colorRulesButton
|
||||
//
|
||||
this.colorRulesButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.colorRulesButton.Text = "Color rules...";
|
||||
this.colorRulesButton.Click += new System.EventHandler(this.colorRulesButton_Click);
|
||||
//
|
||||
// closeButton
|
||||
//
|
||||
this.closeButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
|
||||
this.closeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.closeButton.Text = "Close";
|
||||
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
|
||||
//
|
||||
// filterPanel
|
||||
//
|
||||
this.filterPanel.ColumnCount = 8;
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 42F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 42F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 105F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 72F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 180F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F));
|
||||
this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F));
|
||||
this.filterPanel.Controls.Add(this.filterLabel, 0, 0);
|
||||
this.filterPanel.Controls.Add(this.filterTextBox, 1, 0);
|
||||
this.filterPanel.Controls.Add(this.levelLabel, 2, 0);
|
||||
this.filterPanel.Controls.Add(this.levelComboBox, 3, 0);
|
||||
this.filterPanel.Controls.Add(this.applicationLabel, 4, 0);
|
||||
this.filterPanel.Controls.Add(this.applicationComboBox, 5, 0);
|
||||
this.filterPanel.Controls.Add(this.applyFilterButton, 6, 0);
|
||||
this.filterPanel.Controls.Add(this.clearFilterButton, 7, 0);
|
||||
this.filterPanel.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.filterPanel.Location = new System.Drawing.Point(0, 31);
|
||||
this.filterPanel.Name = "filterPanel";
|
||||
this.filterPanel.Padding = new System.Windows.Forms.Padding(6, 5, 6, 5);
|
||||
this.filterPanel.RowCount = 1;
|
||||
this.filterPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.filterPanel.Size = new System.Drawing.Size(1184, 38);
|
||||
this.filterPanel.TabIndex = 1;
|
||||
//
|
||||
// filter controls
|
||||
//
|
||||
this.filterLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.filterLabel.AutoSize = true;
|
||||
this.filterLabel.Text = "Filter";
|
||||
this.filterTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.filterTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.filterTextBox_KeyDown);
|
||||
this.levelLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.levelLabel.AutoSize = true;
|
||||
this.levelLabel.Text = "Level";
|
||||
this.levelComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.levelComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.levelComboBox.SelectedIndexChanged += new System.EventHandler(this.filterValueChanged);
|
||||
this.applicationLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.applicationLabel.AutoSize = true;
|
||||
this.applicationLabel.Text = "Application";
|
||||
this.applicationComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.applicationComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.applicationComboBox.SelectedIndexChanged += new System.EventHandler(this.filterValueChanged);
|
||||
this.applyFilterButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.applyFilterButton.Text = "Apply";
|
||||
this.applyFilterButton.Click += new System.EventHandler(this.applyFilterButton_Click);
|
||||
this.clearFilterButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.clearFilterButton.Text = "Reset";
|
||||
this.clearFilterButton.Click += new System.EventHandler(this.clearFilterButton_Click);
|
||||
//
|
||||
// logContextMenu
|
||||
//
|
||||
this.logContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.copySelectionMenuItem,
|
||||
this.copyLineMenuItem,
|
||||
this.copyAllMenuItem});
|
||||
this.copySelectionMenuItem.Text = "Copy selection";
|
||||
this.copySelectionMenuItem.Click += new System.EventHandler(this.copySelectionMenuItem_Click);
|
||||
this.copyLineMenuItem.Text = "Copy current line";
|
||||
this.copyLineMenuItem.Click += new System.EventHandler(this.copyLineMenuItem_Click);
|
||||
this.copyAllMenuItem.Text = "Copy all visible logs";
|
||||
this.copyAllMenuItem.Click += new System.EventHandler(this.copyAllButton_Click);
|
||||
//
|
||||
// logView
|
||||
//
|
||||
this.logView.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.logView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.logView.ContextMenuStrip = this.logContextMenu;
|
||||
this.logView.DetectUrls = false;
|
||||
this.logView.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.logView.Font = new System.Drawing.Font("Consolas", 9F);
|
||||
this.logView.HideSelection = false;
|
||||
this.logView.Location = new System.Drawing.Point(0, 69);
|
||||
this.logView.Name = "logView";
|
||||
this.logView.ReadOnly = true;
|
||||
this.logView.Size = new System.Drawing.Size(1184, 554);
|
||||
this.logView.TabIndex = 2;
|
||||
this.logView.Text = "";
|
||||
this.logView.WordWrap = true;
|
||||
//
|
||||
// statusStrip
|
||||
//
|
||||
this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.receiverStatusLabel,
|
||||
this.statusSpacer,
|
||||
this.countStatusLabel});
|
||||
this.statusStrip.Location = new System.Drawing.Point(0, 623);
|
||||
this.statusStrip.Name = "statusStrip";
|
||||
this.statusStrip.Size = new System.Drawing.Size(1184, 22);
|
||||
this.statusStrip.TabIndex = 3;
|
||||
this.receiverStatusLabel.Text = "Listening";
|
||||
this.statusSpacer.Spring = true;
|
||||
this.countStatusLabel.Text = "Received: 0 | Visible: 0";
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1184, 645);
|
||||
this.Controls.Add(this.logView);
|
||||
this.Controls.Add(this.filterPanel);
|
||||
this.Controls.Add(this.mainToolStrip);
|
||||
this.Controls.Add(this.statusStrip);
|
||||
this.KeyPreview = true;
|
||||
this.MinimumSize = new System.Drawing.Size(860, 480);
|
||||
this.Name = "MainForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Application live diagnostic";
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown);
|
||||
this.mainToolStrip.ResumeLayout(false);
|
||||
this.mainToolStrip.PerformLayout();
|
||||
this.filterPanel.ResumeLayout(false);
|
||||
this.filterPanel.PerformLayout();
|
||||
this.logContextMenu.ResumeLayout(false);
|
||||
this.statusStrip.ResumeLayout(false);
|
||||
this.statusStrip.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
using AppDiagnostic.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
private readonly Func<int> connectedClientCountProvider;
|
||||
private readonly Func<bool> activationRequestProvider;
|
||||
private readonly Timer refreshTimer;
|
||||
private readonly Font regularLogFont;
|
||||
private readonly Font boldLogFont;
|
||||
private List<LogColorRule> colorRules;
|
||||
private long lastRenderedVersion = -1;
|
||||
private int observedEntryCount;
|
||||
private int visibleEntryCount;
|
||||
private bool loadingFilters;
|
||||
|
||||
public MainForm() : this(null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public MainForm(Func<int> connectedClientCountProvider, Func<bool> activationRequestProvider)
|
||||
{
|
||||
this.connectedClientCountProvider = connectedClientCountProvider;
|
||||
this.activationRequestProvider = activationRequestProvider;
|
||||
InitializeComponent();
|
||||
Icon = Properties.Resources.TBF_icon;
|
||||
|
||||
regularLogFont = new Font(logView.Font, FontStyle.Regular);
|
||||
boldLogFont = new Font(logView.Font, FontStyle.Bold);
|
||||
colorRules = LogColorRuleRepository.Load();
|
||||
|
||||
InitializeFilters();
|
||||
|
||||
refreshTimer = new Timer { Interval = 250 };
|
||||
refreshTimer.Tick += refreshTimer_Tick;
|
||||
refreshTimer.Start();
|
||||
|
||||
RefreshView(true);
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
refreshTimer.Stop();
|
||||
refreshTimer.Dispose();
|
||||
regularLogFont.Dispose();
|
||||
boldLogFont.Dispose();
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
private void InitializeFilters()
|
||||
{
|
||||
loadingFilters = true;
|
||||
levelComboBox.Items.AddRange(new object[] { "All levels", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" });
|
||||
levelComboBox.SelectedIndex = 0;
|
||||
applicationComboBox.Items.Add("All applications");
|
||||
applicationComboBox.SelectedIndex = 0;
|
||||
loadingFilters = false;
|
||||
}
|
||||
|
||||
private void refreshTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
ProcessActivationRequest();
|
||||
RefreshView(false);
|
||||
}
|
||||
|
||||
private void ProcessActivationRequest()
|
||||
{
|
||||
if (activationRequestProvider == null || !activationRequestProvider())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (WindowState == FormWindowState.Minimized)
|
||||
{
|
||||
WindowState = FormWindowState.Normal;
|
||||
}
|
||||
|
||||
Show();
|
||||
BringToFront();
|
||||
Activate();
|
||||
}
|
||||
|
||||
private void RefreshView(bool forceFullRefresh)
|
||||
{
|
||||
List<DiagnosticLogEntry> snapshot = DiagnosticLogStore.Instance.GetSnapshot();
|
||||
UpdateApplicationFilter(snapshot);
|
||||
|
||||
if (pauseButton.Checked)
|
||||
{
|
||||
UpdateStatus(snapshot.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
long currentVersion = DiagnosticLogStore.Instance.Version;
|
||||
if (!forceFullRefresh && currentVersion == lastRenderedVersion)
|
||||
{
|
||||
UpdateStatus(snapshot.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
bool canAppend = !forceFullRefresh && snapshot.Count > observedEntryCount;
|
||||
if (canAppend)
|
||||
{
|
||||
AppendEntries(snapshot.Skip(observedEntryCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
RebuildView(snapshot);
|
||||
}
|
||||
|
||||
observedEntryCount = snapshot.Count;
|
||||
lastRenderedVersion = currentVersion;
|
||||
UpdateStatus(snapshot.Count);
|
||||
}
|
||||
|
||||
private void RebuildView(IEnumerable<DiagnosticLogEntry> entries)
|
||||
{
|
||||
logView.SuspendLayout();
|
||||
logView.Clear();
|
||||
visibleEntryCount = 0;
|
||||
AppendEntries(entries, false);
|
||||
logView.ResumeLayout();
|
||||
|
||||
if (autoScrollButton.Checked)
|
||||
{
|
||||
ScrollToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendEntries(IEnumerable<DiagnosticLogEntry> entries, bool scrollAfterAppend = true)
|
||||
{
|
||||
int originalSelectionStart = logView.SelectionStart;
|
||||
int originalSelectionLength = logView.SelectionLength;
|
||||
|
||||
foreach (DiagnosticLogEntry entry in entries)
|
||||
{
|
||||
if (!MatchesFilter(entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AppendEntry(entry);
|
||||
visibleEntryCount++;
|
||||
}
|
||||
|
||||
if (scrollAfterAppend && autoScrollButton.Checked)
|
||||
{
|
||||
ScrollToEnd();
|
||||
}
|
||||
else if (!autoScrollButton.Checked)
|
||||
{
|
||||
int safeStart = Math.Min(originalSelectionStart, logView.TextLength);
|
||||
int safeLength = Math.Min(originalSelectionLength, logView.TextLength - safeStart);
|
||||
logView.Select(safeStart, safeLength);
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendEntry(DiagnosticLogEntry entry)
|
||||
{
|
||||
string text = DiagnosticLogFormatter.Format(entry);
|
||||
|
||||
if (logView.TextLength > 0)
|
||||
{
|
||||
logView.AppendText(Environment.NewLine);
|
||||
}
|
||||
|
||||
int startIndex = logView.TextLength;
|
||||
logView.AppendText(text);
|
||||
LogColorizer.Apply(logView, startIndex, text.Length, text, colorRules, regularLogFont, boldLogFont);
|
||||
logView.Select(logView.TextLength, 0);
|
||||
}
|
||||
|
||||
private bool MatchesFilter(DiagnosticLogEntry entry)
|
||||
{
|
||||
string selectedLevel = levelComboBox.SelectedItem as string;
|
||||
if (!string.IsNullOrEmpty(selectedLevel) && selectedLevel != "All levels" && !string.Equals(entry.Level, selectedLevel, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string selectedApplication = applicationComboBox.SelectedItem as string;
|
||||
if (!string.IsNullOrEmpty(selectedApplication) && selectedApplication != "All applications" && !string.Equals(entry.ApplicationName, selectedApplication, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string filter = filterTextBox.Text.Trim();
|
||||
return filter.Length == 0 || DiagnosticLogFormatter.Format(entry).IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
private void UpdateApplicationFilter(IEnumerable<DiagnosticLogEntry> entries)
|
||||
{
|
||||
string selectedApplication = applicationComboBox.SelectedItem as string ?? "All applications";
|
||||
List<string> applications = entries.Select(entry => entry.ApplicationName).Where(name => !string.IsNullOrWhiteSpace(name)).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(name => name).ToList();
|
||||
List<string> currentApplications = applicationComboBox.Items.Cast<string>().Skip(1).ToList();
|
||||
|
||||
if (applications.SequenceEqual(currentApplications, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
loadingFilters = true;
|
||||
applicationComboBox.BeginUpdate();
|
||||
applicationComboBox.Items.Clear();
|
||||
applicationComboBox.Items.Add("All applications");
|
||||
applicationComboBox.Items.AddRange(applications.Cast<object>().ToArray());
|
||||
applicationComboBox.SelectedItem = applicationComboBox.Items.Cast<string>().FirstOrDefault(item => string.Equals(item, selectedApplication, StringComparison.OrdinalIgnoreCase)) ?? "All applications";
|
||||
applicationComboBox.EndUpdate();
|
||||
loadingFilters = false;
|
||||
}
|
||||
|
||||
private void UpdateStatus(int storedCount)
|
||||
{
|
||||
int clients = connectedClientCountProvider?.Invoke() ?? 0;
|
||||
receiverStatusLabel.Text = pauseButton.Checked ? $"Paused | Connected sources: {clients}" : $"Listening | Connected sources: {clients}";
|
||||
countStatusLabel.Text = $"Received: {DiagnosticLogStore.Instance.TotalReceived:N0} | Stored: {storedCount:N0} | Visible: {visibleEntryCount:N0}";
|
||||
}
|
||||
|
||||
private void ScrollToEnd()
|
||||
{
|
||||
logView.Select(logView.TextLength, 0);
|
||||
logView.ScrollToCaret();
|
||||
}
|
||||
|
||||
private void pauseButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
pauseButton.Text = pauseButton.Checked ? "Resume" : "Pause";
|
||||
|
||||
if (!pauseButton.Checked)
|
||||
{
|
||||
RefreshView(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateStatus(DiagnosticLogStore.Instance.GetSnapshot().Count);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
RefreshView(true);
|
||||
}
|
||||
|
||||
private void clearButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DiagnosticLogStore.Instance.Clear();
|
||||
observedEntryCount = 0;
|
||||
visibleEntryCount = 0;
|
||||
RefreshView(true);
|
||||
}
|
||||
|
||||
private void saveButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var dialog = new SaveFileDialog())
|
||||
{
|
||||
dialog.Filter = "Text files (*.txt)|*.txt|Log files (*.log)|*.log|All files (*.*)|*.*";
|
||||
dialog.Title = "Save visible diagnostic logs";
|
||||
dialog.DefaultExt = "log";
|
||||
dialog.FileName = $"AppDiagnostic_{DateTime.Now:yyyyMMdd_HHmmss}.log";
|
||||
|
||||
if (dialog.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(dialog.FileName, logView.Text);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
MessageBox.Show(this, $"Unable to save diagnostic logs: {exception.Message}", "Save error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
CopySelectionOrCurrentLine();
|
||||
}
|
||||
|
||||
private void copySelectionMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (logView.SelectionLength > 0)
|
||||
{
|
||||
CopyText(logView.SelectedText);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyLineMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
CopyCurrentLine();
|
||||
}
|
||||
|
||||
private void copyAllButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
CopyText(logView.Text);
|
||||
}
|
||||
|
||||
private void CopySelectionOrCurrentLine()
|
||||
{
|
||||
if (logView.SelectionLength > 0)
|
||||
{
|
||||
CopyText(logView.SelectedText);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyCurrentLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyCurrentLine()
|
||||
{
|
||||
if (logView.Lines.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int lineIndex = logView.GetLineFromCharIndex(logView.SelectionStart);
|
||||
if (lineIndex >= 0 && lineIndex < logView.Lines.Length)
|
||||
{
|
||||
CopyText(logView.Lines[lineIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyText(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(text);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
MessageBox.Show(this, $"Unable to copy text: {exception.Message}", "Clipboard error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void wrapButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
logView.WordWrap = wrapButton.Checked;
|
||||
}
|
||||
|
||||
private void alwaysOnTopButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
TopMost = alwaysOnTopButton.Checked;
|
||||
}
|
||||
|
||||
private void colorRulesButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var editor = new ColorRuleEditorForm(colorRules))
|
||||
{
|
||||
if (editor.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
colorRules = editor.Rules;
|
||||
|
||||
try
|
||||
{
|
||||
LogColorRuleRepository.Save(colorRules);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
MessageBox.Show(this, $"Unable to save color rules: {exception.Message}", "Settings error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
RefreshView(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyFilterButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
RefreshView(true);
|
||||
}
|
||||
|
||||
private void clearFilterButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
loadingFilters = true;
|
||||
filterTextBox.Clear();
|
||||
levelComboBox.SelectedIndex = 0;
|
||||
applicationComboBox.SelectedIndex = 0;
|
||||
loadingFilters = false;
|
||||
RefreshView(true);
|
||||
}
|
||||
|
||||
private void filterValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!loadingFilters)
|
||||
{
|
||||
RefreshView(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void filterTextBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter)
|
||||
{
|
||||
RefreshView(true);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.KeyCode == Keys.Escape)
|
||||
{
|
||||
clearFilterButton_Click(sender, EventArgs.Empty);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void closeButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void MainForm_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Control && e.KeyCode == Keys.F)
|
||||
{
|
||||
filterTextBox.Focus();
|
||||
filterTextBox.SelectAll();
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.Control && e.KeyCode == Keys.S)
|
||||
{
|
||||
saveButton_Click(sender, EventArgs.Empty);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.KeyCode == Keys.F5)
|
||||
{
|
||||
RefreshView(true);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AppDiagnostic
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
bool isFirstInstance;
|
||||
|
||||
using (var instanceMutex = new Mutex(true, "Sensus.AppDiagnostic.SingleInstance", out isFirstInstance))
|
||||
using (var activationEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "Sensus.AppDiagnostic.Activate"))
|
||||
{
|
||||
if (!isFirstInstance)
|
||||
{
|
||||
activationEvent.Set();
|
||||
return;
|
||||
}
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
using (var diagnosticServer = new DiagnosticPipeServer(DiagnosticLogStore.Instance.Add))
|
||||
{
|
||||
diagnosticServer.Start();
|
||||
Application.Run(new MainForm(() => diagnosticServer.ConnectedClientCount, () => activationEvent.WaitOne(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("AppDiagnostic")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AppDiagnostic")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("fa9abad1-7184-4295-ade8-d44f2e3de6b2")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace AppDiagnostic.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AppDiagnostic.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon TBF_icon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("TBF_icon", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="TBF_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\TBF_icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace AppDiagnostic.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="3.0.3" targetFramework="net472" />
|
||||
</packages>
|
||||
+11
-4
@@ -17,7 +17,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
@@ -30,12 +30,17 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\packages\log4net.2.0.2\lib\net40-full\log4net.dll</HintPath>
|
||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.2.2\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
@@ -90,7 +95,9 @@
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Forms\ListViewEx.resx">
|
||||
<DependentUpon>ListViewEx.cs</DependentUpon>
|
||||
|
||||
@@ -96,6 +96,16 @@ namespace Common
|
||||
return string.Format("{0},{1},{2}", User().UserName, User2.UserName, User3.UserName);
|
||||
}
|
||||
|
||||
public static string GetEncodedString(string legalizator)
|
||||
{
|
||||
if (User() == null || User().UserName == null) return string.Empty;
|
||||
return string.Format("{0}~{1}~{2}",
|
||||
User().UserName,
|
||||
User().FullName == null ? string.Empty : User().FullName,
|
||||
legalizator == null ? string.Empty : legalizator);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the current user number or 0
|
||||
/// </summary>
|
||||
|
||||
+94
-8
@@ -1,9 +1,10 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
@@ -185,16 +186,70 @@ namespace Common
|
||||
Count,
|
||||
}
|
||||
|
||||
public enum FlowNames
|
||||
{
|
||||
QnQtQmin = 0,
|
||||
Q3Q2Q1 = 1,
|
||||
QpQi = 2,
|
||||
Count,
|
||||
}
|
||||
|
||||
public enum ProfileType
|
||||
{
|
||||
Q3R,
|
||||
QnClassColdWater,
|
||||
QnClassHotWater,
|
||||
QpQi,
|
||||
CompoundQ3RQ3R,
|
||||
CompoundQnClassQnClass,
|
||||
CompoundQ3RQnClass,
|
||||
CompoundQnClassQ3R,
|
||||
CompoundQpQiQpQi,
|
||||
Manual,
|
||||
Count,
|
||||
}
|
||||
|
||||
public enum FlowId
|
||||
{
|
||||
Any,
|
||||
Q4,
|
||||
Q3,
|
||||
Q2,
|
||||
Q1,
|
||||
Q4Main,
|
||||
Q3Main,
|
||||
Q2Main,
|
||||
Q1Main,
|
||||
Q4Aux,
|
||||
Q3Aux,
|
||||
Q2Aux,
|
||||
Q1Aux,
|
||||
Qmax,
|
||||
Qn,
|
||||
Qt,
|
||||
Qmin,
|
||||
QmaxMain,
|
||||
QnMain,
|
||||
QtMain,
|
||||
QminMain,
|
||||
QmaxAux,
|
||||
QnAux,
|
||||
QtAux,
|
||||
QminAux,
|
||||
Qp,
|
||||
Qp10,
|
||||
Qi,
|
||||
QpMain,
|
||||
Qp10Main,
|
||||
QiMain,
|
||||
QpAux,
|
||||
Qp10Aux,
|
||||
QiAux,
|
||||
Qdetected,
|
||||
Qfall,
|
||||
Qrise,
|
||||
}
|
||||
|
||||
public enum ErrorLimitType
|
||||
{
|
||||
Manual,
|
||||
@@ -235,11 +290,20 @@ namespace Common
|
||||
CompoundAux,
|
||||
Compound,
|
||||
HeatMeterVolume,
|
||||
HeatMeterEnergy,
|
||||
HeatMeterMass,//...MF
|
||||
HeatMeterEnergy,
|
||||
SingleOrCompound, /// Only used when querying results
|
||||
}
|
||||
|
||||
public enum Medium
|
||||
public enum PulsesTypeByQuantity : short
|
||||
{
|
||||
[Description("dm3")] Volume_dm3,
|
||||
[Description("kg")] Mass_kg,
|
||||
|
||||
Count
|
||||
}
|
||||
|
||||
public enum Medium
|
||||
{
|
||||
[Description("")] NotSpecified,
|
||||
#if LANG_PL
|
||||
@@ -266,11 +330,13 @@ namespace Common
|
||||
[Description("V")] V, /// vertical
|
||||
[Description("STR")] S, /// standrohre
|
||||
[Description("F")] F, /// fall
|
||||
[Description("H/V")] HV, /// horizontal / vertical
|
||||
#else
|
||||
[Description("H")] H, /// horizontal
|
||||
[Description("V")] V, /// vertical
|
||||
[Description("S")] S, /// steig
|
||||
[Description("F")] F, /// fall
|
||||
[Description("H")] H, /// horizontal
|
||||
[Description("V")] V, /// vertical
|
||||
[Description("S")] S, /// steig
|
||||
[Description("F")] F, /// fall
|
||||
[Description("H/V")] HV, /// horizontal / vertical
|
||||
#endif
|
||||
Count
|
||||
}
|
||||
@@ -464,8 +530,10 @@ namespace Common
|
||||
public enum TestProfile
|
||||
{
|
||||
UserDefined,
|
||||
UserDefinedCompound,
|
||||
UserDefinedHeatMeter,
|
||||
Protected, /// The first protected one
|
||||
ProtectedCompound,
|
||||
ProtectedHeatMeter,
|
||||
}
|
||||
|
||||
@@ -640,7 +708,16 @@ namespace Common
|
||||
Count,
|
||||
}
|
||||
|
||||
public enum ImageRotation
|
||||
public enum DivResolution : int
|
||||
{
|
||||
[Description("1 ms (0.25 s)")] _1ms = 0,
|
||||
[Description("2 ms (0.5 s)")] _2ms = 1,
|
||||
[Description("4 ms (1 s)")] _4ms = 2,
|
||||
[Description("8 ms (2 s)")] _8ms = 3,
|
||||
Count,
|
||||
}
|
||||
|
||||
public enum ImageRotation
|
||||
{
|
||||
[Description("0 deg")] None,
|
||||
[Description("90 deg")] Deg90,
|
||||
@@ -762,6 +839,15 @@ namespace Common
|
||||
E63 = (1L << 62),
|
||||
}
|
||||
|
||||
//...MF
|
||||
public enum FlowType : int
|
||||
{
|
||||
none,
|
||||
volume,
|
||||
mass,
|
||||
Count,
|
||||
}
|
||||
|
||||
#region iPERL enums
|
||||
|
||||
public enum Side
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
///
|
||||
/// Copyright (c) 2021-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
|
||||
namespace Common.Forms
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
///
|
||||
/// Copyright (c) 2021-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -53,20 +56,20 @@ namespace Common.Forms
|
||||
public event EventHandler<MessageEventArgs> UpdateMessageHandler;
|
||||
void OnUpdateMessage(object sender, MessageEventArgs args)
|
||||
{
|
||||
if (args.Message != null) label1.Text = args.Message;
|
||||
if (args != null && args.Message != null) label1.Text = args.Message;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called from the state machine when an operation forces a modeless dialog close.
|
||||
/// </summary>
|
||||
public static void CloseForm()
|
||||
public void CloseForm()
|
||||
{
|
||||
if (CloseFormHandler == null) return;
|
||||
try { CloseFormHandler(null, null); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
static public event EventHandler<EventArgs> CloseFormHandler;
|
||||
public event EventHandler<EventArgs> CloseFormHandler;
|
||||
void OnCloseForm(object sender, EventArgs args)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Common.Iperl
|
||||
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
|
||||
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
|
||||
public Int32 FlipTime() { return Impedance; }
|
||||
public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
|
||||
public decimal TimestampDec() { return (decimal)TimestampExt; }
|
||||
public double VolumeDelta(double scalingFactor, OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
|
||||
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
|
||||
public string Label()
|
||||
|
||||
+131
-23
@@ -2,6 +2,7 @@
|
||||
/// Copyright (c) 2016-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
@@ -33,6 +34,20 @@ namespace Common
|
||||
[Description("m3/m")] m3pm, /// 1 m3/m = 60 m3/h
|
||||
[Description("cf/s")] cfs, /// 1 cubic foot per second = 101.9406477312 m3/h
|
||||
|
||||
|
||||
[Description("g/s")] gps, /// 1 g/s = 0.0036 t/h
|
||||
[Description("g/min")] gpm, /// 1 g/min = 0.00006 t/h
|
||||
[Description("g/h")] gph, /// 1 g/h = 0.000001 t/h
|
||||
[Description("kg/s")] kgps, /// 1 kg/s = 3.6 t/h
|
||||
[Description("kg/min")] kgpm, /// 1 kg/min = 0.06 t/h
|
||||
[Description("kg/h")] kgph, /// 1 kg/h = 0.001 t/h
|
||||
[Description("t/s")] tps, /// 1 t/s = 3600 t/h
|
||||
[Description("t/min")] tpm, /// 1 t/min = 60 t/h
|
||||
[Description("t/h")] tph, /// 1 t/h = 1 t/h
|
||||
[Description("lb/s")] lbps, /// 1 lb/s ≈ 1.633 t/h
|
||||
[Description("lb/min")] lbpm, /// 1 lb/min ≈ 0.027216 t/h
|
||||
[Description("lb/h")] lbph, /// 1 lb/h ≈ 0.0004536 t/h
|
||||
|
||||
[Description("g")] g, /// 0.001 kg
|
||||
[Description("oz")] oz, /// 0.0283495231 kg
|
||||
[Description("lb")] lb, /// 0.45359237 kg
|
||||
@@ -105,6 +120,14 @@ namespace Common
|
||||
///
|
||||
[Description("pulse/kWh")] ppkWh, /// * 1 pulse/kWh
|
||||
[Description("kWh/pulse")] kWhpp, /// 1 kWh/pulse
|
||||
|
||||
///
|
||||
[Description("A")] A, /// *1 A
|
||||
[Description("mA")] mA, /// 1 mA = 0.001 A
|
||||
///
|
||||
[Description("V")] V, /// *1 V
|
||||
[Description("mV")] mV, /// 1 mV = 0.001 V
|
||||
|
||||
|
||||
Count
|
||||
}
|
||||
@@ -135,6 +158,8 @@ namespace Common
|
||||
[Description("Boolean")] Boolean,
|
||||
[Description("Datum und Uhrzeit")] DateTime,
|
||||
[Description("Aufgezählt")] Enumerated,
|
||||
[Description("Strom")] Current,
|
||||
[Description("Spannung")] Voltage,
|
||||
#elif LANG_PL
|
||||
[Description("Objętość")] Volume,
|
||||
[Description("Przepływ")] Flow,
|
||||
@@ -158,6 +183,8 @@ namespace Common
|
||||
[Description("Boolean")] Boolean,
|
||||
[Description("Data i czas")] DateTime,
|
||||
[Description("Wyliczone")] Enumerated,
|
||||
[Description("Prąd")] Current,
|
||||
[Description("Napięcie")] Voltage,
|
||||
#elif LANG_CS
|
||||
[Description("Objem")] Volume,
|
||||
[Description("Průtok")] Flow,
|
||||
@@ -181,6 +208,8 @@ namespace Common
|
||||
[Description("Boolean")] Boolean,
|
||||
[Description("Datum a čas")] DateTime,
|
||||
[Description("Vyjmenované")] Enumerated,
|
||||
[Description("Proud")] Current,
|
||||
[Description("Napětí")] Voltage,
|
||||
#elif LANG_IT
|
||||
[Description("Volume")] Volume,
|
||||
[Description("Flusso")] Flow,
|
||||
@@ -204,10 +233,16 @@ namespace Common
|
||||
[Description("Boolean")] Boolean,
|
||||
[Description("Data e ora")] DateTime,
|
||||
[Description("Enumerato")] Enumerated,
|
||||
[Description("Corrente")] Current,
|
||||
[Description("Voltaggio")] Voltage,
|
||||
#else
|
||||
[Description("RegisterReader")] RegisterReader,
|
||||
[Description("MultiFunctionalVariables")] MultiFunctionalVariables,
|
||||
[Description("VolumeFlow")] VolumeFlow,
|
||||
[Description("Volume")] Volume,
|
||||
[Description("Flow")] Flow,
|
||||
[Description("Mass")] Mass,
|
||||
[Description("MassFlow")] MassFlow,
|
||||
[Description("Mass")] Mass,
|
||||
[Description("Time")] Time,
|
||||
[Description("Temperature")] Temperature,
|
||||
[Description("Pressure")] Pressure,
|
||||
@@ -218,6 +253,8 @@ namespace Common
|
||||
[Description("Energy")] Energy,
|
||||
[Description("Pulses")] Pulses,
|
||||
[Description("Pulses/liter")] PulsePerLtr,
|
||||
[Description("Pulses/kg")] PulsePerKilogram, //...MF
|
||||
[Description("Pulses/Unit")] PulsePerUnit,//...MF
|
||||
[Description("Pulses/kWh")] PulsePerKWh,
|
||||
[Description("Conductivity")] Conductivity,
|
||||
|
||||
@@ -227,6 +264,8 @@ namespace Common
|
||||
[Description("Boolean")] Boolean,
|
||||
[Description("Date and time")] DateTime,
|
||||
[Description("Enumerated")] Enumerated,
|
||||
[Description("Current")] Current,
|
||||
[Description("Voltage")] Voltage,
|
||||
#endif
|
||||
Count,
|
||||
}
|
||||
@@ -242,59 +281,103 @@ namespace Common
|
||||
{
|
||||
return unit == Unit.l || unit == Unit.m3ph || unit == Unit.kg || unit == Unit.s || unit == Unit.C ||
|
||||
unit == Unit.bar || unit == Unit.RPct || unit == Unit.Pct || unit == Unit.mm || unit == Unit.kgpm3 ||
|
||||
unit == Unit.J || unit == Unit.uSpcm || unit == Unit.ppl || unit == Unit.ppkWh;
|
||||
unit == Unit.J || unit == Unit.uSpcm || unit == Unit.ppl || unit == Unit.ppkWh || unit == Unit.A ||
|
||||
unit == Unit.V;
|
||||
}
|
||||
|
||||
public static bool IsQuantity(Unit unit, Quantity quantity)
|
||||
{
|
||||
return (quantity == GetQuantity(unit));
|
||||
return GetQuantity(unit).Contains(quantity);
|
||||
}
|
||||
|
||||
public static Quantity GetQuantity(Unit unit)
|
||||
public static Quantity[] GetQuantity(Unit unit)
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case Unit.pulse:
|
||||
case Unit.degree:
|
||||
return Quantity.Pulses;
|
||||
return new[] { Quantity.Pulses };
|
||||
|
||||
case Unit.ml:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.l:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.dm3:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.USgal:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.UKgal:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.cf:
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
case Unit.m3:
|
||||
return Quantity.Volume;
|
||||
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
|
||||
|
||||
case Unit.lph:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.cfph:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.lpm:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.USgalpm:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.m3ph:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.lps:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.USgalps:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.m3pm:
|
||||
return new[] { Quantity.Flow };
|
||||
case Unit.cfs:
|
||||
return Quantity.Flow;
|
||||
return new[] { Quantity.Flow };
|
||||
|
||||
case Unit.gps:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.gpm:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.gph:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.kgps:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.kgpm:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.kgph:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.tps:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.tpm:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.tph:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.lbps:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.lbpm:
|
||||
return new[] { Quantity.MassFlow};
|
||||
case Unit.lbph:
|
||||
return new[] { Quantity.MassFlow};
|
||||
|
||||
case Unit.g:
|
||||
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
|
||||
case Unit.oz:
|
||||
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
|
||||
case Unit.lb:
|
||||
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
|
||||
case Unit.kg:
|
||||
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
|
||||
case Unit.t:
|
||||
return Quantity.Mass;
|
||||
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
|
||||
|
||||
case Unit.ms:
|
||||
case Unit.s:
|
||||
case Unit.min:
|
||||
case Unit.hour:
|
||||
return Quantity.Time;
|
||||
return new[] { Quantity.Time };
|
||||
|
||||
case Unit.C:
|
||||
case Unit.F:
|
||||
case Unit.K:
|
||||
return Quantity.Temperature;
|
||||
return new[] { Quantity.Temperature };
|
||||
|
||||
case Unit.Pa:
|
||||
case Unit.hPa:
|
||||
@@ -304,14 +387,14 @@ namespace Common
|
||||
case Unit.psi:
|
||||
case Unit.bar:
|
||||
case Unit.MPa:
|
||||
return Quantity.Pressure;
|
||||
return new[] { Quantity.Pressure };
|
||||
|
||||
case Unit.RPct:
|
||||
return Quantity.Humidity;
|
||||
return new[] { Quantity.Humidity };
|
||||
|
||||
case Unit.Promile:
|
||||
case Unit.Pct:
|
||||
return Quantity.Error;
|
||||
return new[] { Quantity.Error };
|
||||
|
||||
case Unit.mm:
|
||||
case Unit.cm:
|
||||
@@ -320,23 +403,23 @@ namespace Common
|
||||
case Unit.foot:
|
||||
case Unit.yard:
|
||||
case Unit.m:
|
||||
return Quantity.Length;
|
||||
return new[] { Quantity.Length };
|
||||
|
||||
case Unit.kgpm3:
|
||||
case Unit.kgpm3:
|
||||
case Unit.kgpl:
|
||||
return Quantity.Density;
|
||||
return new[] { Quantity.Density };
|
||||
|
||||
case Unit.J:
|
||||
case Unit.J:
|
||||
case Unit.kJ:
|
||||
case Unit.MJ:
|
||||
case Unit.Wh:
|
||||
case Unit.kWh:
|
||||
case Unit.MWh:
|
||||
return Quantity.Energy;
|
||||
return new[] { Quantity.Energy };
|
||||
|
||||
case Unit.uSpcm:
|
||||
case Unit.mSpm:
|
||||
return Quantity.Conductivity;
|
||||
return new[] { Quantity.Conductivity };
|
||||
|
||||
case Unit.ppl:
|
||||
case Unit.ppdm3:
|
||||
@@ -346,19 +429,29 @@ namespace Common
|
||||
case Unit.dm3pp:
|
||||
case Unit.lpdeg:
|
||||
case Unit.dm3pdeg:
|
||||
return Quantity.PulsePerLtr;
|
||||
return new[] { Quantity.PulsePerLtr };
|
||||
|
||||
case Unit.ppkWh:
|
||||
case Unit.kWhpp:
|
||||
return Quantity.PulsePerKWh;
|
||||
return new[] { Quantity.PulsePerKWh };
|
||||
|
||||
case Unit.A:
|
||||
case Unit.mA:
|
||||
return new[] { Quantity.Current };
|
||||
|
||||
case Unit.V:
|
||||
case Unit.mV:
|
||||
return new[] { Quantity.Voltage };
|
||||
|
||||
default:
|
||||
return Quantity.Number;
|
||||
return new[] { Quantity.Number };
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
|
||||
public static bool IsVolumeFlow(Unit unit) { return IsQuantity(unit, Quantity.VolumeFlow); }
|
||||
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
|
||||
public static bool IsFlow(Unit unit) { return IsQuantity(unit, Quantity.Flow); }
|
||||
public static bool IsMassFlow(Unit unit) { return IsQuantity(unit, Quantity.MassFlow); }
|
||||
public static bool IsMass(Unit unit) { return IsQuantity(unit, Quantity.Mass); }
|
||||
public static bool IsTime(Unit unit) { return IsQuantity(unit, Quantity.Time); }
|
||||
public static bool IsTemperature(Unit unit) { return IsQuantity(unit, Quantity.Temperature); }
|
||||
@@ -372,6 +465,8 @@ namespace Common
|
||||
public static bool IsPulsePerLtr(Unit unit) { return IsQuantity(unit, Quantity.PulsePerLtr); }
|
||||
public static bool IsPulsePerKWh(Unit unit) { return IsQuantity(unit, Quantity.PulsePerKWh); }
|
||||
public static bool IsConductivity(Unit unit) { return IsQuantity(unit, Quantity.Conductivity); }
|
||||
public static bool IsCurrent(Unit unit) { return IsQuantity(unit, Quantity.Current); }
|
||||
public static bool IsVoltage(Unit unit) { return IsQuantity(unit, Quantity.Voltage); }
|
||||
|
||||
|
||||
|
||||
@@ -455,6 +550,13 @@ namespace Common
|
||||
case Unit.dm3pp:
|
||||
case Unit.lpdeg:
|
||||
case Unit.dm3pdeg: return (v <= float.Epsilon) ? 0 : 1/v;
|
||||
|
||||
/// Current: internal representation in A
|
||||
case Unit.mA: return 1000 * v; /// 1000 mA = 1 A
|
||||
|
||||
/// Voltage: internal representation in V
|
||||
case Unit.mV: return 1000 * v; /// 1000 mV = 1 V
|
||||
|
||||
|
||||
default: return v; /// Do not convert
|
||||
}
|
||||
@@ -534,6 +636,12 @@ namespace Common
|
||||
|
||||
/// Electrical conductivity
|
||||
case Unit.mSpm: return 10 * v;
|
||||
|
||||
/// Current: internal representation in A
|
||||
case Unit.mA: return 0.001 * v; /// 1 mA = 0.001 A
|
||||
|
||||
/// Voltage: internal representation in V
|
||||
case Unit.mV: return 0.001 * v; /// 1 mV = 0.001 V
|
||||
|
||||
/// Invert
|
||||
case Unit.kWhpp:
|
||||
|
||||
+33
-5
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2021-2022 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2021-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
|
||||
@@ -20,6 +20,29 @@ namespace Common
|
||||
return (format == "F0") ? value.ToString("F0") : value.ToString(format).TrimEnd(new char[] { '0' });
|
||||
}
|
||||
|
||||
public static FlowNames ProfileType2FlowNames(ProfileType pt, bool isAux = false)
|
||||
{
|
||||
switch (pt)
|
||||
{
|
||||
case ProfileType.Q3R:
|
||||
case ProfileType.CompoundQ3RQ3R:
|
||||
return FlowNames.Q3Q2Q1;
|
||||
case ProfileType.CompoundQ3RQnClass:
|
||||
return isAux ? FlowNames.QnQtQmin : FlowNames.Q3Q2Q1;
|
||||
case ProfileType.QnClassColdWater:
|
||||
case ProfileType.QnClassHotWater:
|
||||
case ProfileType.CompoundQnClassQnClass:
|
||||
return FlowNames.QnQtQmin;
|
||||
case ProfileType.CompoundQnClassQ3R:
|
||||
return isAux ? FlowNames.Q3Q2Q1 : FlowNames.QnQtQmin;
|
||||
case ProfileType.QpQi:
|
||||
case ProfileType.CompoundQpQiQpQi:
|
||||
return FlowNames.QpQi;
|
||||
default:
|
||||
return FlowNames.Q3Q2Q1;
|
||||
}
|
||||
}
|
||||
|
||||
public static string SignificantDigitsToFmt(double value, int sigDigits)
|
||||
{
|
||||
if (sigDigits == 6)
|
||||
@@ -278,16 +301,21 @@ namespace Common
|
||||
int number = (date.Year % 10) + 10 * (date.Month - 1) + 120 * date.Day;
|
||||
string passwordOfDay = Convert.ToString(number, 8);
|
||||
|
||||
return (userName.Equals("milan") && password.Equals("kremik")) ||
|
||||
return (userName.Equals("milan") && password.Equals("kraken")) ||
|
||||
(userName.Equals("bumi") && password.Equals("70630")) ||
|
||||
(userName.Equals("igor") && password.Equals("mojronko8")) ||
|
||||
(userName.Equals("MARIAN") && password.Equals("NM-309BN")) ||
|
||||
(userName.Equals("lubo1212") && password.Equals("Tatry52")) ||
|
||||
(userName.Equals("Michal") && password.Equals("1236natahA8")) ||
|
||||
(userName.Equals("Michal") && password.Equals("Plok789456123")) ||
|
||||
(userName.Equals("martin") && password.Equals("vaclavek84")) ||
|
||||
(userName.Equals("pakan") && password.Equals("kuriatko")) ||
|
||||
(userName.Equals("augustin") && password.Equals("jaugust")) ||
|
||||
(userName.Equals("jan") && password.Equals("jaugust")) ||
|
||||
(userName.Equals("JCermak") && password.Equals("Zt6911")) ||
|
||||
(userName.Equals("gilles") && password.Equals("alibaba")) ||
|
||||
(userName.Equals("michal") && password.Equals("mojnelson8")) ||
|
||||
(userName.Equals("marek") && password.Equals("mareciino")) ||
|
||||
#if DEBUG
|
||||
(userName.Equals("Sensus Developers") && password.Equals("5fbg12gf5hn8nhy1fr")) ||
|
||||
#endif
|
||||
(userName.Equals(passwordOfDay) && password.Equals(passwordOfDay));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="2.0.15" targetFramework="net472" />
|
||||
<package id="NLog" version="5.2.2" targetFramework="net472" />
|
||||
</packages>
|
||||
@@ -19,7 +19,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
@@ -30,7 +30,7 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;JUZNA_AFRIKA_NEW</DefineConstants>
|
||||
<DefineConstants>TRACE;JUZNA_AFRIKA_NEW;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
@@ -43,7 +43,7 @@
|
||||
<HintPath>..\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\packages\log4net.2.0.2\lib\net40-full\log4net.dll</HintPath>
|
||||
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data">
|
||||
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
|
||||
@@ -68,6 +68,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CalendarEvent\ICalendarEvent.cs" />
|
||||
<Compile Include="Data.cs" />
|
||||
<Compile Include="Entities\BenchPath.cs" />
|
||||
<Compile Include="Entities\CustomEvent.cs" />
|
||||
<Compile Include="Entities\Component.cs" />
|
||||
@@ -95,6 +96,7 @@
|
||||
<Compile Include="Entities\VirtualBenchStep.cs" />
|
||||
<Compile Include="CalendarEvent\Utils.cs" />
|
||||
<Compile Include="FluentCommon.cs" />
|
||||
<Compile Include="Formulas.cs" />
|
||||
<Compile Include="Mappings\BenchPathMap.cs" />
|
||||
<Compile Include="Mappings\ComponentMap.cs" />
|
||||
<Compile Include="Mappings\ComponentProcedureMap.cs" />
|
||||
@@ -115,6 +117,7 @@
|
||||
<Compile Include="Mappings\UncertaintyMap.cs" />
|
||||
<Compile Include="Mappings\UserMap.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PurchaseResources.cs" />
|
||||
<Compile Include="Resources\Strings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
@@ -123,7 +126,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Strings.cs.resx" />
|
||||
<EmbeddedResource Include="Resources\Strings.de.resx" />
|
||||
<EmbeddedResource Include="Resources\Strings.de.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\Strings.fr.resx" />
|
||||
<EmbeddedResource Include="Resources\Strings.it.resx" />
|
||||
<EmbeddedResource Include="Resources\Strings.pl.resx" />
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
|
||||
//formulas.cs has been added cause iPerl from master-2 ...MF
|
||||
|
||||
namespace Config
|
||||
{
|
||||
public class Data
|
||||
{
|
||||
public const string AdminUsername = "admin";
|
||||
public const string AdminPassword = "staratura";
|
||||
public const string SQLiteDbFName = "SQLite.db";
|
||||
|
||||
#if DN100 || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || CEVAK_200
|
||||
public const int WMsCount = 3;
|
||||
public const int LineSize = 3;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 1;
|
||||
#elif MUNICH
|
||||
public const int WMsCount = 3;
|
||||
public const int LineSize = 3;
|
||||
public const int CompoundWMsCount = 3;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 3;
|
||||
#elif MALTA_WSD25
|
||||
public const int WMsCount = 6;
|
||||
public const int LineSize = 6;
|
||||
public const int CompoundWMsCount = 0;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 1;
|
||||
#elif BADGER_MALA_TRAT || BERLIN || FUZHOU_150 || FUZHOU_300 || GELSENWASSER || GENESIS || IZRAEL_200 || PETERSBURG_200 || SENTEC || SLM_150 || TORINO_50
|
||||
public const int WMsCount = 6;
|
||||
public const int LineSize = 6;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 1;
|
||||
#elif PUCHONG_200
|
||||
public const int WMsCount = 6;
|
||||
public const int LineSize = 6;
|
||||
public const int CompoundWMsCount = 3;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 3;
|
||||
#elif RUM_MOB
|
||||
public const int WMsCount = 8;
|
||||
public const int LineSize = 8;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif TURA_SPECIAL
|
||||
public const int WMsCount = 6;
|
||||
public const int LineSize = 6;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif DEWA_300 || FUZHOU_100 || ROMA_200 || LUXEMBURG_40
|
||||
public const int WMsCount = 10;
|
||||
public const int LineSize = 10;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif DUBAJ_50
|
||||
public const int WMsCount = 10;
|
||||
public const int LineSize = 5;
|
||||
public const int CompoundWMsCount = 0;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif SLM_END || WARSAW_END
|
||||
public const int WMsCount = 10;
|
||||
public const int LineSize = 5;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = 4;
|
||||
#elif SLM_50
|
||||
public const int WMsCount = 12;
|
||||
public const int LineSize = 12;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 6;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif ALZIR_25 || BAHRAIN_50 || CEVAK_40 || FEWA_50 || FILIPINY_50 || FUZHOU_50 || HONGKONG_50 || IZRAEL_25 || JUZNA_AFRIKA_50 || KEMPNO_50 || KRAKOW_50 || MILWAUKEE || MURES_40 || PETERSBURG_50 || TORUN_50 || WARSAW_50 || ZAMBIA || ZODINO
|
||||
public const int WMsCount = 20;
|
||||
public const int LineSize = 10;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif TURA_IPERL || TURA_IPERL_NEW
|
||||
public const int WMsCount = 40;
|
||||
public const int LineSize = 20;
|
||||
public const int CompoundWMsCount = 1;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#elif IZRAEL_50
|
||||
public const int WMsCount = 40;
|
||||
public const int LineSize = 10;
|
||||
public const int CompoundWMsCount = 0;
|
||||
public const int HeatMetersCount = 0;
|
||||
public const int MaxPartNr = WMsCount / LineSize;
|
||||
#endif
|
||||
|
||||
public static double RealDensity = 0; /// true water density [kg/m3]
|
||||
public static double AtTemperature = 0; /// measured at temperature [°C]
|
||||
public static double Buoyancy = 0;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,9 @@ namespace Config.Entities
|
||||
public virtual string PressMtrUp { get; set; }
|
||||
public virtual string PressMtrDown { get; set; }
|
||||
public virtual string PressMtrDelta { get; set; }
|
||||
public virtual string ElectricMtrUp { get; set; }
|
||||
public virtual string ElectricMtrDown { get; set; }
|
||||
public virtual string ElectricMtrDelta { get; set; }
|
||||
public virtual string StopBFValve { get; set; }
|
||||
|
||||
/// Valves
|
||||
@@ -59,6 +62,9 @@ namespace Config.Entities
|
||||
result.PressMtrUp = PressMtrUp;
|
||||
result.PressMtrDown = PressMtrDown;
|
||||
result.PressMtrDelta = PressMtrDelta;
|
||||
result.ElectricMtrUp = ElectricMtrUp;
|
||||
result.ElectricMtrDown = ElectricMtrDown;
|
||||
result.ElectricMtrDelta = ElectricMtrDelta;
|
||||
result.StopBFValve = StopBFValve;
|
||||
result.ValvesOpen = ValvesOpen;
|
||||
result.ValvesClose = ValvesClose;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Config.Entities
|
||||
public virtual Unit FlowUnit { get; set; } /// Not mapped to database, used in UI
|
||||
public virtual string Selector { get; set; }
|
||||
public virtual string Pump { get; set; }
|
||||
public virtual string RegVPositions { get; set; } /// Positions of regulation valves in % separated by ';'
|
||||
public virtual string RegVPositions { get; set; } /// Positions of regulation valves in Category.Feeding in % separated by ';'
|
||||
|
||||
/// Valves
|
||||
public virtual string ValvesOpen { get; set; }
|
||||
|
||||
@@ -18,12 +18,14 @@ namespace Config.Entities
|
||||
public virtual Unit FlowUnit { get; set; } /// Not mapped to database, used in UI
|
||||
public virtual string Selector { get; set; }
|
||||
public virtual string RegValve { get; set; }
|
||||
public virtual string FlowMeter { get; set; }
|
||||
public virtual float PidCoef { get; set; } /// PID coefficient for the regulation path
|
||||
public virtual int RegulMinStep { get; set; }
|
||||
public virtual string FlowMeter { get; set; }
|
||||
public virtual float PidCoef { get; set; } /// PID coefficient for the regulation path
|
||||
public virtual string StartValve { get; set; }
|
||||
public virtual string Diverter { get; set; }
|
||||
public virtual string TempMtrDiv { get; set; }
|
||||
public virtual string Scale { get; set; }
|
||||
public virtual string RegVPositions { get; set; } /// Positions of regulation valves in Category.Output in % separated by ';'
|
||||
|
||||
/// Valves
|
||||
public virtual string ValvesOpen { get; set; }
|
||||
@@ -38,6 +40,7 @@ namespace Config.Entities
|
||||
{
|
||||
ValvesOpen = string.Empty;
|
||||
ValvesClose = string.Empty;
|
||||
RegulMinStep = 0;
|
||||
}
|
||||
|
||||
public OutputPath(string name, int itemNr)
|
||||
@@ -45,7 +48,9 @@ namespace Config.Entities
|
||||
{
|
||||
Name = name;
|
||||
ItemNr = itemNr;
|
||||
}
|
||||
RegulMinStep = 0;
|
||||
|
||||
}
|
||||
|
||||
public virtual OutputPath Clone(string name, int itemNr)
|
||||
{
|
||||
@@ -57,12 +62,14 @@ namespace Config.Entities
|
||||
result.FlowUnit = FlowUnit;
|
||||
result.Selector = Selector;
|
||||
result.RegValve = RegValve;
|
||||
result.FlowMeter = FlowMeter;
|
||||
result.RegulMinStep = RegulMinStep;
|
||||
result.FlowMeter = FlowMeter;
|
||||
result.PidCoef = PidCoef;
|
||||
result.StartValve = StartValve;
|
||||
result.Diverter = Diverter;
|
||||
result.TempMtrDiv = TempMtrDiv;
|
||||
result.Scale = Scale;
|
||||
result.RegVPositions= RegVPositions;
|
||||
result.ValvesOpen = ValvesOpen;
|
||||
result.ValvesClose = ValvesClose;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2019-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Globalization;
|
||||
@@ -16,7 +16,9 @@ namespace Config.Entities
|
||||
public virtual int Id { get; protected set; }
|
||||
public virtual int ItemNr { get; set; }
|
||||
public virtual string Name { get; set; }
|
||||
public virtual int Part { get; set; } /// Part=0 ... test of all WM-s /// Part>0 ... part of a set of tests with the same Name: subset of WM-s is given by MetersPath
|
||||
public virtual int Part { get; set; } /// Part=0 ... test of all WM-s
|
||||
/// Part>0 ... part of a set of tests with the same Name: subset of WM-s is given by MetersPath
|
||||
public virtual FlowId FlowId { get; set; }
|
||||
public virtual double CoefQfrom { get; set; } /// Water flow low limit in [m3/h]
|
||||
public virtual double CoefQto { get; set; } /// Water flow high limit in [m3/h]
|
||||
public virtual double ErrLimLo { get; set; } /// in [%] usually < 0, in case of heat meters: 1=class1, 2=class2, 3=class3
|
||||
@@ -27,6 +29,7 @@ namespace Config.Entities
|
||||
public virtual double PressLimHi { get; set; } /// [bar] max. water pressure
|
||||
public virtual sbyte Publish { get; set; } /// 0=no, 1=in all protocols, 2=on screen, 3=internal
|
||||
public virtual bool Evaluate { get; set; }
|
||||
public virtual string Method { get; set; } /// Test method (component name)
|
||||
|
||||
public virtual sbyte E1 { get; set; } ///
|
||||
public virtual sbyte E2 { get; set; } ///
|
||||
@@ -81,6 +84,7 @@ namespace Config.Entities
|
||||
PressLimHi = 16.0; /// [bar]
|
||||
Publish = (sbyte)Common.Publish.Always;
|
||||
Evaluate = true;
|
||||
Method = string.Empty;
|
||||
|
||||
E1 = (sbyte)ErrorFlagsMode.On;
|
||||
E2 = (sbyte)ErrorFlagsMode.On;
|
||||
@@ -140,6 +144,7 @@ namespace Config.Entities
|
||||
result.PressLimHi = PressLimHi;
|
||||
result.Publish = Publish;
|
||||
result.Evaluate = Evaluate;
|
||||
result.Method = Method;
|
||||
|
||||
result.E1 = E1;
|
||||
result.E2 = E2;
|
||||
@@ -183,6 +188,7 @@ namespace Config.Entities
|
||||
|
||||
output.WriteLine(Name);
|
||||
output.WriteLine(Part);
|
||||
output.WriteLine(((ushort)FlowId).ToString(ci));
|
||||
output.WriteLine(CoefQfrom.ToString(ci));
|
||||
output.WriteLine(CoefQto.ToString(ci));
|
||||
output.WriteLine(ErrLimLo.ToString(ci));
|
||||
@@ -193,6 +199,7 @@ namespace Config.Entities
|
||||
output.WriteLine(PressLimHi.ToString(ci));
|
||||
output.WriteLine(Publish.ToString());
|
||||
output.WriteLine(Evaluate.ToString());
|
||||
output.WriteLine(Method);
|
||||
|
||||
output.WriteLine(E1.ToString());
|
||||
output.WriteLine(E2.ToString());
|
||||
@@ -241,16 +248,36 @@ namespace Config.Entities
|
||||
|
||||
tst.Name = firstLine;
|
||||
tst.Part = int.Parse(input.ReadLine());
|
||||
tst.FlowId = (FlowId)ushort.Parse(input.ReadLine(), ci);
|
||||
tst.CoefQfrom = double.Parse(input.ReadLine(), ci);
|
||||
tst.CoefQto = double.Parse(input.ReadLine(), ci);
|
||||
tst.ErrLimLo = double.Parse(input.ReadLine(), ci);
|
||||
tst.ErrLimHi = double.Parse(input.ReadLine(), ci);
|
||||
tst.TempLimLo = double.Parse(input.ReadLine(), ci);
|
||||
tst.TempLimHi = double.Parse(input.ReadLine(), ci);
|
||||
tst.Publish = sbyte.Parse(input.ReadLine());
|
||||
tst.PressLimLo = double.Parse(input.ReadLine(), ci);
|
||||
tst.PressLimHi = double.Parse(input.ReadLine(), ci);
|
||||
tst.Publish = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.Evaluate = bool.Parse(input.ReadLine());
|
||||
tst.Method = input.ReadLine();
|
||||
|
||||
/// TODO (E1 .. E21)
|
||||
tst.E1 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E2 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E3 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E4 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E5 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E6 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E7 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E8 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E9 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E10 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E11 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E12 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E13 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E14 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E15 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E16 = sbyte.Parse(input.ReadLine(), ci);
|
||||
tst.E21 = sbyte.Parse(input.ReadLine(), ci);
|
||||
|
||||
tst.Delta_Q_pct = double.Parse(input.ReadLine(), ci);
|
||||
tst.Delta_T = double.Parse(input.ReadLine(), ci);
|
||||
@@ -283,6 +310,7 @@ namespace Config.Entities
|
||||
|
||||
if (Name != firstLine) { diff.AppendFormat(fmt, "Name", Name, firstLine); };
|
||||
ln = inp.ReadLine(); if (ln != Part.ToString()) { diff.AppendFormat(fmt, "Part", Part.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != ((ushort)FlowId).ToString()){diff.AppendFormat(fmt, "FlowId", ((ushort)FlowId).ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != CoefQfrom.ToString(ci)) { diff.AppendFormat(fmt, "CoefQfrom", CoefQfrom.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != CoefQto.ToString(ci)) { diff.AppendFormat(fmt, "CoefQto", CoefQto.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != ErrLimLo.ToString(ci)) { diff.AppendFormat(fmt, "ErrLimLo", ErrLimLo.ToString(ci), ln); };
|
||||
@@ -293,6 +321,7 @@ namespace Config.Entities
|
||||
ln = inp.ReadLine(); if (ln != PressLimHi.ToString(ci)) { diff.AppendFormat(fmt, "Pressure_max", PressLimHi.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Publish.ToString()) { diff.AppendFormat(fmt, "Publish", Publish.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Evaluate.ToString()) { diff.AppendFormat(fmt, "Evaluate", Evaluate.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Method) { diff.AppendFormat(fmt, "Method", Method, ln); };
|
||||
|
||||
ln = inp.ReadLine(); if (ln != E1.ToString()) { diff.AppendFormat(fmt, "E1", E1.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != E2.ToString()) { diff.AppendFormat(fmt, "E2", E2.ToString(), ln); };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -47,7 +47,7 @@ namespace Config.Entities
|
||||
public virtual int AltProcPeriod { get; set; } /// Period of alternative procedures (0 = no alt. procedure)
|
||||
|
||||
public virtual float DN { get; set; } /// Not mapped to DB, valid in ProceduresCtrl for procedure filtering only
|
||||
public virtual float Qn { get; set; } /// - ' ' -
|
||||
public virtual double Qn { get; set; } /// - ' ' -
|
||||
public virtual string MClass { get; set; } /// - ' ' -
|
||||
public virtual string Producer { get; set; } /// - ' ' -
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ namespace Config.Entities
|
||||
output.WriteLine(CreationTime.ToString(CultureInfo.InvariantCulture));
|
||||
output.WriteLine(LastChgUser);
|
||||
output.WriteLine(LastChgTime.ToString(CultureInfo.InvariantCulture));
|
||||
output.WriteLine(((sbyte)ProfileType).ToString());
|
||||
output.WriteLine(((sbyte)ErrorLimitType).ToString());
|
||||
|
||||
foreach (var test in Tests) { test.Export(output); }
|
||||
output.WriteLine();
|
||||
@@ -96,7 +98,8 @@ namespace Config.Entities
|
||||
result.CreationTime = DateTime.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
|
||||
result.LastChgUser = input.ReadLine();
|
||||
result.LastChgTime = DateTime.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
|
||||
string line = input.ReadLine();
|
||||
result.ProfileType = (ProfileType)sbyte.Parse(input.ReadLine());
|
||||
result.ErrorLimitType = (ErrorLimitType)sbyte.Parse(input.ReadLine());
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
+38
-17
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -19,14 +19,15 @@ namespace Config.Entities
|
||||
public virtual string Name { get; set; }
|
||||
public virtual int Part { get; set; } /// Part=0 ... test of all WM-s
|
||||
/// Part>0 ... part of a set of tests with the same Name: subset of WM-s is given by MetersPath
|
||||
public virtual TestProfile Profile { get; set; } /// UserDefined, Protected, UserDefinedHeatMeter, ProtectedHeatMeter
|
||||
public virtual TestProfile Profile { get; set; } /// UserDefined, UserDefinedCompound, UserDefinedHeatMeter, Protected, ProtectedCompound, ProtectedHeatMeter
|
||||
public virtual sbyte Publish { get; set; } /// 0=no, 1=in all protocols, 2=on screen, 3=internal
|
||||
public virtual bool DoEvaluate { get; set; }
|
||||
public virtual double Qtg { get; set; } /// Target water flow [m3/h]
|
||||
public virtual double Qfrom { get; set; } /// Water flow low limit in [m3/h]
|
||||
public virtual double Qto { get; set; } /// Water flow high limit in [m3/h]
|
||||
public virtual double Qtg { get; set; } /// When == -1 => Qtg is determined by the test method, otherwise Qtg is in [m3/h],
|
||||
public virtual double Qfrom { get; set; } /// Water flow low limit in [m3/h] or in [%] of Qtg
|
||||
public virtual double Qto { get; set; } /// Water flow high limit in [m3/h] or in [%] of Qtg
|
||||
public virtual bool IsFromToInPct { get; set; } /// true: Qfrom and Qto are in % of Qtg, false: Qfrom and Qto are in [m3/h]
|
||||
public virtual double Volume { get; set; } /// Test volume (target) in [l]
|
||||
public virtual double TestTime { get; set; } /// Test time (estimate) in [s]
|
||||
public virtual double TestTime { get; set; } /// Test time (estimate) in [s]
|
||||
public virtual string Method { get; set; }
|
||||
public virtual float ErrLimLo { get; set; } /// in [%] usually < 0, in case of heat meters: 1=class1, 2=class2, 3=class3
|
||||
public virtual float ErrLimHi { get; set; } /// in [%] usually > 0, in case of heat meters: -Qn in m3/h
|
||||
@@ -57,6 +58,11 @@ namespace Config.Entities
|
||||
public virtual string TransBetween { get; set; }
|
||||
public virtual string TransAfter { get; set; }
|
||||
|
||||
public virtual IList<ComponentTest> MoreParams { get; set; }
|
||||
|
||||
public virtual Procedure Procedure { get; set; }
|
||||
|
||||
/// Additional stuff not mapped into the database
|
||||
public virtual bool IsOuterLoopStart { get; set; } /// Not mapped to database
|
||||
public virtual bool IsOuterLoopEnd { get; set; } /// Not mapped to database
|
||||
|
||||
@@ -72,12 +78,17 @@ namespace Config.Entities
|
||||
public virtual Unit TempUnit { get; set; } /// Not mapped to database, used in ProcedureDlg / Metrology1Tab
|
||||
public virtual Unit PressUnit { get; set; } /// Not mapped to database, used in ProcedureDlg / Metrology1Tab
|
||||
public virtual Unit LengthUnit { get; set; } /// Not mapped to database, used in ProcedureDlg / Metrology1Tab
|
||||
public virtual Unit ElectricUnit { get; set; } /// Not mapped to database, used in ProcedureDlg / Metrology1Tab
|
||||
|
||||
public virtual IList<ComponentTest> MoreParams { get; set; }
|
||||
|
||||
public virtual Procedure Procedure { get; set; }
|
||||
|
||||
/// ------------- Additional stuff not mapped into the database -------------
|
||||
/// Wrappers
|
||||
public virtual double QfromM3ph()
|
||||
{
|
||||
return !IsFromToInPct ? Qfrom : Qtg >= 0 ? Qtg * Qfrom / 100 : 0;
|
||||
}
|
||||
public virtual double QtoM3ph()
|
||||
{
|
||||
return !IsFromToInPct ? Qto : Qtg >= 0 ? Qtg * Qto / 100 : 0;
|
||||
}
|
||||
|
||||
public Test()
|
||||
{
|
||||
@@ -90,6 +101,7 @@ namespace Config.Entities
|
||||
Profile = TestProfile.UserDefined;
|
||||
Publish = (sbyte)Common.Publish.Always;
|
||||
DoEvaluate = true;
|
||||
IsFromToInPct = false;
|
||||
ErrLimLo = -2.0f; /// [%] lower error limit
|
||||
ErrLimHi = 2.0f; /// [%] upper error limit
|
||||
Uncertainty = 0;
|
||||
@@ -159,7 +171,8 @@ namespace Config.Entities
|
||||
result.Qtg = Qtg;
|
||||
result.Qfrom = Qfrom;
|
||||
result.Qto = Qto;
|
||||
result.Volume = Volume;
|
||||
result.IsFromToInPct = IsFromToInPct;
|
||||
result.Volume = Volume;
|
||||
result.TestTime = TestTime;
|
||||
result.Method = Method;
|
||||
result.ErrLimLo = ErrLimLo;
|
||||
@@ -192,10 +205,12 @@ namespace Config.Entities
|
||||
result.TransAfter = TransAfter;
|
||||
result.VolumeUnit = VolumeUnit;
|
||||
result.FlowUnit = FlowUnit;
|
||||
result.FlowUnit = FlowUnit;
|
||||
result.MassUnit = MassUnit;
|
||||
result.TempUnit = TempUnit;
|
||||
result.PressUnit = PressUnit;
|
||||
result.LengthUnit = LengthUnit;
|
||||
result.ElectricUnit = ElectricUnit;
|
||||
foreach (var prms in MoreParams) { result.MoreParams.Add(prms.Clone()); }
|
||||
|
||||
return result;
|
||||
@@ -212,6 +227,7 @@ namespace Config.Entities
|
||||
output.WriteLine(Qtg.ToString(ci));
|
||||
output.WriteLine(Qfrom.ToString(ci));
|
||||
output.WriteLine(Qto.ToString(ci));
|
||||
output.WriteLine(IsFromToInPct.ToString());
|
||||
output.WriteLine(Volume.ToString(ci));
|
||||
output.WriteLine(TestTime.ToString(ci));
|
||||
output.WriteLine(Method);
|
||||
@@ -264,6 +280,7 @@ namespace Config.Entities
|
||||
tst.Qtg = double.Parse(input.ReadLine(), ci);
|
||||
tst.Qfrom = double.Parse(input.ReadLine(), ci);
|
||||
tst.Qto = double.Parse(input.ReadLine(), ci);
|
||||
tst.IsFromToInPct = bool.Parse(input.ReadLine());
|
||||
tst.Volume = double.Parse(input.ReadLine(), ci);
|
||||
tst.TestTime = double.Parse(input.ReadLine(), ci);
|
||||
tst.Method = input.ReadLine();
|
||||
@@ -293,8 +310,11 @@ namespace Config.Entities
|
||||
tst.TransBetween = input.ReadLine();
|
||||
string line = input.ReadLine();
|
||||
tst.Profile = line.Equals(TestProfile.ProtectedHeatMeter.ToString()) ? TestProfile.ProtectedHeatMeter
|
||||
: line.Equals(TestProfile.UserDefinedHeatMeter.ToString()) ? TestProfile.UserDefinedHeatMeter
|
||||
: line.Equals(TestProfile.Protected.ToString()) ? TestProfile.Protected : TestProfile.UserDefined; /// UserDefined is the default
|
||||
: line.Equals(TestProfile.ProtectedCompound.ToString()) ? TestProfile.ProtectedCompound
|
||||
: line.Equals(TestProfile.Protected.ToString()) ? TestProfile.Protected
|
||||
: line.Equals(TestProfile.UserDefinedHeatMeter.ToString()) ? TestProfile.UserDefinedHeatMeter
|
||||
: line.Equals(TestProfile.UserDefinedCompound.ToString()) ? TestProfile.UserDefinedCompound
|
||||
: TestProfile.UserDefined; /// UserDefined is the default
|
||||
tst.TransAfter = input.ReadLine();
|
||||
|
||||
while (true)
|
||||
@@ -327,6 +347,7 @@ namespace Config.Entities
|
||||
ln = inp.ReadLine(); if (ln != Qtg.ToString(ci)) { diff.AppendFormat(fmt, "Qtg", Qtg.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Qfrom.ToString(ci)) { diff.AppendFormat(fmt, "Qfrom", Qfrom.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Qto.ToString(ci)) { diff.AppendFormat(fmt, "Qto", Qto.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != IsFromToInPct.ToString()) { diff.AppendFormat(fmt, "IsFromToInPct", IsFromToInPct.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Volume.ToString(ci)) { diff.AppendFormat(fmt, "Volume", Volume.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != TestTime.ToString(ci)) { diff.AppendFormat(fmt, "TstTime", TestTime.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Method) { diff.AppendFormat(fmt, "Method", Method, ln); };
|
||||
@@ -334,11 +355,11 @@ namespace Config.Entities
|
||||
ln = inp.ReadLine(); if (ln != ErrLimHi.ToString(ci)) { diff.AppendFormat(fmt, "ErrLimHi", ErrLimHi.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Uncertainty.ToString(ci)) { diff.AppendFormat(fmt, "Uncertainty", Uncertainty.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != Repeats.ToString(ci)) { diff.AppendFormat(fmt, "Repeats", Repeats.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != DoDraining.ToString(ci)) { diff.AppendFormat(fmt, "DoDraining", DoDraining.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != DoDrainingAfter.ToString(ci)) { diff.AppendFormat(fmt, "DoDrainingAfter", DoDrainingAfter.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != DoDraining.ToString()) { diff.AppendFormat(fmt, "DoDraining", DoDraining.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != DoDrainingAfter.ToString()) { diff.AppendFormat(fmt, "DoDrainingAfter", DoDrainingAfter.ToString(), ln); };
|
||||
ln = inp.ReadLine(); if (ln != TempLimLo.ToString(ci)) { diff.AppendFormat(fmt, "TempLimLo", TempLimLo.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != TempLimHi.ToString(ci)) { diff.AppendFormat(fmt, "TempLimHi", TempLimHi.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != TempControl) { diff.AppendFormat(fmt, "TempController", TempControl, ln); };
|
||||
ln = inp.ReadLine(); if (ln != TempControl) { diff.AppendFormat(fmt, "TempController", TempControl, ln); };
|
||||
ln = inp.ReadLine(); if (ln != PumpPower.ToString(ci)) { diff.AppendFormat(fmt, "PumpPower", PumpPower.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != MassRepeats.ToString(ci)) { diff.AppendFormat(fmt, "MassRepeats", MassRepeats.ToString(ci), ln); };
|
||||
ln = inp.ReadLine(); if (ln != MassSpread.ToString(ci)) { diff.AppendFormat(fmt, "MassSpread", MassSpread.ToString(ci), ln); };
|
||||
|
||||
@@ -128,10 +128,11 @@ namespace Config
|
||||
case GID.Administrators:
|
||||
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
|
||||
case GID.TraceabilityManagement:
|
||||
#elif KEMPNO_50 || KRAKOW_50 || TORUN_50 || WARSAW_END
|
||||
//#elif LANG_PL
|
||||
#endif
|
||||
case GID.MetrologicalAuthority:
|
||||
case GID.WaterMeterAuthority:
|
||||
#endif
|
||||
|
||||
admin.AddGroup(group);
|
||||
session.SaveOrUpdate(group); /// Save this group
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using Common;
|
||||
|
||||
//formulas.cs has been added cause iPerl from master-2 ...MF
|
||||
|
||||
namespace Config
|
||||
{
|
||||
public static class Formulas
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Formulas));
|
||||
|
||||
|
||||
///
|
||||
/// Wrappers
|
||||
///
|
||||
public static double RealDensity() { return Data.RealDensity; }
|
||||
public static double AtTemperature() { return Data.AtTemperature; }
|
||||
public static double Buoyancy() { return Data.Buoyancy; }
|
||||
|
||||
|
||||
/// Private tables with coeficients to calculate specific enthalpy
|
||||
static readonly int[] Ii;
|
||||
static readonly int[] Ji;
|
||||
static readonly double[] ni;
|
||||
|
||||
/// Private table with coeficients to calculate temperature of a platinum thermometer
|
||||
static readonly double[] Di;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
static Formulas()
|
||||
{
|
||||
///
|
||||
/// Initialize tables to calculate specific enthalpies
|
||||
///
|
||||
Ii = new int[34] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32 };
|
||||
Ji = new int[34] { -2, -1, 0, 1, 2, 3, 4, 5, -9, -7, -1, 0, 1, 3, -3, 0, 1, 3, 17, -4, 0, 6, -5, -2, 10, -8, -11, -6, -29, -31, -38, -39, -40, -41 };
|
||||
ni = new double[34] {
|
||||
0.14632971213167, /// 1
|
||||
-0.84548187169114, /// 2
|
||||
-0.37563603672040E1, /// 3
|
||||
0.33855169168385E1, /// 4
|
||||
-0.95791963387872, /// 5
|
||||
0.15772038513228, /// 6
|
||||
-0.16616417199501E-1, /// 7
|
||||
0.81214629983568E-3, /// 8
|
||||
0.28319080123804E-3, /// 9
|
||||
-0.60706301565874E-3, /// 10
|
||||
-0.18990068218419E-1, /// 11
|
||||
-0.32529748770505E-1, /// 12
|
||||
-0.21841717175414E-1, /// 13
|
||||
-0.52838357969930E-4, /// 14
|
||||
-0.47184321073267E-3, /// 15
|
||||
-0.30001780793026E-3, /// 16
|
||||
0.47661393906987E-4, /// 17
|
||||
-0.44141845330846E-5, /// 18
|
||||
-0.72694996297594E-15, /// 19
|
||||
-0.31679644845054E-4, /// 20
|
||||
-0.28270797985312E-5, /// 21
|
||||
-0.85205128120103E-9, /// 22
|
||||
-0.22425281908000E-5, /// 23
|
||||
-0.65171222895601E-6, /// 24
|
||||
-0.14341729937924E-12, /// 25
|
||||
-0.40516996860117E-6, /// 26
|
||||
-0.12734301741641E-8, /// 27
|
||||
-0.17424871230634E-9, /// 28
|
||||
-0.68762131295531E-18, /// 29
|
||||
0.14478307828521E-19, /// 30
|
||||
0.26335781662795E-22, /// 31
|
||||
-0.11947622640071E-22, /// 32
|
||||
0.18228094581404E-23, /// 33
|
||||
-0.93537087292458E-25, /// 34
|
||||
};
|
||||
|
||||
///
|
||||
/// Initialize a table to calculate temperature of a platinum thermometer from resistance
|
||||
///
|
||||
Di = new double[]
|
||||
{
|
||||
439.932854,
|
||||
472.418020,
|
||||
37.684494,
|
||||
7.472018,
|
||||
2.920828,
|
||||
0.005184,
|
||||
-0.963864,
|
||||
-0.188732,
|
||||
0.191203,
|
||||
0.049025,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate density of distilled water from temperature
|
||||
/// </summary>
|
||||
/// <param name="t">ITS-90 temperature in [°C]</param>
|
||||
/// <returns>Density in [kg/m3]</returns>
|
||||
public static double DistilledWaterDensityFromTemp(double t)
|
||||
{
|
||||
if (t <= 40)
|
||||
{
|
||||
const double c0 = 999.839564;
|
||||
const double c1 = 0.067998613;
|
||||
const double c2 = -0.0091101468;
|
||||
const double c3 = 0.00010058299;
|
||||
const double c4 = -0.0000011275659;
|
||||
const double c5 = 6.5985371e-09;
|
||||
|
||||
return ((((c5 * t + c4) * t + c3) * t + c2) * t + c1) * t + c0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const double a0 = 9.9983952E2;
|
||||
const double a1 = 1.6952577E1;
|
||||
const double a2 = -7.9905127E-3;
|
||||
const double a3 = -4.6241757E-5;
|
||||
const double a4 = 1.0584601E-7;
|
||||
const double a5 = -2.8103006E-10;
|
||||
const double b = 1.6887236E-2;
|
||||
|
||||
return (((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t + a0) / (1.0 + b * t);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate density of distilled water from temperature (obsolete)
|
||||
/// </summary>
|
||||
/// <param name="t">IPTS-68 temperature in [°C]</param>
|
||||
/// <returns>Density in [kg/m3]</returns>
|
||||
public static double DistilledWaterDensityFromTempIPTS68(double t)
|
||||
{
|
||||
const double a0 = 999.842594;
|
||||
const double a1 = 0.06793952;
|
||||
const double a2 = -0.009095290;
|
||||
const double a3 = 0.0001001685;
|
||||
const double a4 = -0.000001120083;
|
||||
const double a5 = 6.536332e-09;
|
||||
|
||||
return ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t + a0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate density by comparing calculated data and data from a certificate
|
||||
/// </summary>
|
||||
/// <param name="realDensity">Density from a certificate in [kg/m3]</param>
|
||||
/// <param name="atTemperature">Temperature from a certificate in [°C]</param>
|
||||
/// <returns>Density correction in [kg/m3]</returns>
|
||||
public static double DensityCorrection(double realDensity, double atTemperature)
|
||||
{
|
||||
/// Calculated data
|
||||
double calculatedDensity = DistilledWaterDensityFromTemp(atTemperature);
|
||||
|
||||
return realDensity - calculatedDensity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate corrected (real) water density from temperature
|
||||
/// </summary>
|
||||
/// <param name="t">Temperature in [°C]</param>
|
||||
/// <returns>Density in [kg/m3]</returns>
|
||||
public static double WaterDensityFromTemp(double t)
|
||||
{
|
||||
return DistilledWaterDensityFromTemp(t) + DensityCorrection(RealDensity(), AtTemperature());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate corrected (real) water density from temperature
|
||||
/// </summary>
|
||||
/// <param name="t">Temperature in [°C]</param>
|
||||
/// <returns>Density in [kg/m3]</returns>
|
||||
public static double WaterDensityFromTempPress(double temp, double pressure)
|
||||
{
|
||||
double x0 = 5.08821E-10;
|
||||
double x1 = 1.2639418;
|
||||
double x2 = 0.2660269;
|
||||
double x3 = 0.3734838;
|
||||
double x4 = 2.0205242;
|
||||
double theta = temp / 100.0;
|
||||
double B = x0 * (((x3 * theta + x2) * theta + x1) * theta + 1) / (1 + x4 * theta);
|
||||
|
||||
return WaterDensityFromTemp(temp) * (1 + B * Units.ConvertTo(Unit.Pa, pressure));
|
||||
}
|
||||
|
||||
|
||||
public static float AirDensityFromAmbientVales(float tempC, float pressureBar, float humiPct)
|
||||
{
|
||||
double pressurePa = 100000.0 * (double)pressureBar; /// [Pa]
|
||||
double tempKelvin = 273.15 + (double)tempC;
|
||||
double coef1 = 1.2811805 / 10000.0 * tempKelvin * tempKelvin
|
||||
- 1.950987 / 100.0 * tempKelvin
|
||||
+ 34.04926034
|
||||
- 6.353631 * 1000.0 / tempKelvin;
|
||||
double coef3 = humiPct / 100.0 * System.Math.Exp(coef1) / pressurePa;
|
||||
double airDensityKgm3 = 0.00348353 * pressurePa * (1.0 - 0.378 * coef3) / tempKelvin; /// kg/m3
|
||||
return (float)airDensityKgm3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert 'pulses' to 'volume', prevent division by zero
|
||||
/// </summary>
|
||||
public static double VolumeFromPulses(int pulses, double pulsesPerLiter)
|
||||
{
|
||||
if (pulsesPerLiter <= double.Epsilon) return 0;
|
||||
return Convert.ToDouble(pulses) / pulsesPerLiter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the error in % from 'measured' and 'true' volume, prevent division by zero
|
||||
/// </summary>
|
||||
public static double ErrorFromVolumes(double measuredVolume, double trueVolume)
|
||||
{
|
||||
if (-float.Epsilon <= trueVolume && trueVolume <= float.Epsilon)
|
||||
{
|
||||
if (-float.Epsilon <= measuredVolume && measuredVolume <= float.Epsilon)
|
||||
{
|
||||
log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, -100.0);
|
||||
return -100.0;
|
||||
}
|
||||
|
||||
log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, 99.0);
|
||||
return 99.0;
|
||||
}
|
||||
|
||||
double error = 100.0 * (measuredVolume - trueVolume) / trueVolume;
|
||||
log.InfoFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates corrected value from a list of corrections by interpolation.
|
||||
/// It is assumed that values in the list 'corrections' are sorted.
|
||||
/// </summary>
|
||||
/// <param name="rawMeasurement">Raw uncorrected value</param>
|
||||
/// <param name="corrections">Sorted (value, correction) pairs</param>
|
||||
/// <returns>Corrected value</returns>
|
||||
public static double CorrectedValue(double rawValue, IList<IMeasurementCorrection> corrections)
|
||||
{
|
||||
return rawValue + GetCorrection(rawValue, corrections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a correction from a list of corrections by interpolation.
|
||||
/// It is assumed that values in the list 'corrections' are sorted.
|
||||
/// </summary>
|
||||
/// <param name="rawMeasurement">Raw uncorrected value</param>
|
||||
/// <param name="corrections">Sorted (value, correction) pairs</param>
|
||||
/// <returns>Corrected value</returns>
|
||||
public static double GetCorrection(double rawValue, IList<IMeasurementCorrection> corrections)
|
||||
{
|
||||
if ((corrections == null) || (corrections.Count == 0)) return 0; /// No correction
|
||||
|
||||
if (rawValue < corrections[0].Measurement)
|
||||
{
|
||||
/// rawValue is below the lowest value in the correction table
|
||||
return corrections[0].Correction;
|
||||
}
|
||||
|
||||
int count = corrections.Count;
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
if (rawValue < corrections[i].Measurement)
|
||||
{
|
||||
double d1 = rawValue - corrections[i - 1].Measurement;
|
||||
double d2 = corrections[i].Measurement - rawValue;
|
||||
|
||||
if (d1 + d2 <= float.Epsilon)
|
||||
{
|
||||
/// Neigboring values in the corection table are close to each other -> calculate the average
|
||||
return (corrections[i - 1].Correction + corrections[i].Correction) / 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Interpolate the correction from neigboring values in the corection table
|
||||
return (corrections[i - 1].Correction * d2 + corrections[i].Correction * d1) / (d1 + d2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// rawValue is above the highest value in the correction table
|
||||
return corrections[count - 1].Correction;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts a measurement error to a correction (used when preparing correction tables).
|
||||
/// </summary>
|
||||
/// <param name="measuredValue">Measured value (in arbitrary units)</param>
|
||||
/// <param name="error">Measurement error in %</param>
|
||||
/// <returns>Correction in the same units as the measured value</returns>
|
||||
public static double CorrectionFromError(double measuredValue, double error)
|
||||
{
|
||||
double trueValue = measuredValue / (1 + error/100);
|
||||
double correction = trueValue - measuredValue;
|
||||
return correction;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the heat coefficient for water
|
||||
/// </summary>
|
||||
/// <param name="pressure">Pressure [bar]</param>
|
||||
/// <param name="T_in">Inlet temperature [°C]</param>
|
||||
/// <param name="T_out">Outlet temperature [°C]</param>
|
||||
/// <param name="flowMeasuredAtInlet">true = flow measured @inlet, false = flow measured @outlet</param>
|
||||
/// <returns> Heat coefficient for water [J/(m3 K)]</returns>
|
||||
public static double HeatCoefficientWater(double pressure, double T_in, double T_out, bool flowMeasuredAtInlet)
|
||||
{
|
||||
if (T_in == T_out) return 0;
|
||||
|
||||
const double R = 461.526; /// [J kg^-1 K^-1]
|
||||
const double p_star_Pa = 16.53E6; /// [Pa] (=16.53 MPa)
|
||||
const double T_star = 1386.0; /// [K]
|
||||
|
||||
double T_in_K = Units.ConvertTo(Unit.K, T_in);
|
||||
double T_out_K = Units.ConvertTo(Unit.K, T_out);
|
||||
double tau_in = T_star / T_in_K;
|
||||
double tau_out = T_star / T_out_K;
|
||||
double pi = Units.ConvertTo(Unit.Pa, pressure) / p_star_Pa;
|
||||
|
||||
double h_in = tau_in * GammaTau(pi, tau_in) * R * T_in_K;
|
||||
double h_out = tau_out * GammaTau(pi, tau_out) * R * T_out_K;
|
||||
|
||||
double ni = flowMeasuredAtInlet ? GammaPi(pi, tau_in) * R * T_in_K / p_star_Pa
|
||||
: GammaPi(pi, tau_out) * R * T_out_K / p_star_Pa;
|
||||
|
||||
return (h_in - h_out) / (ni * (T_in - T_out));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gamma(pi) see also STN EN 1434-1 Annex A (A.4)
|
||||
/// </summary>
|
||||
/// <param name="pi">pi = p / p* where p* = 16.53 MPa</param>
|
||||
/// <param name="tau">tau = T* / T where T* = 1386 K</param>
|
||||
/// <returns>gamma(pi)</returns>
|
||||
static double GammaPi(double pi, double tau)
|
||||
{
|
||||
double result = 0;
|
||||
for (int i = 0; i < 34; i++)
|
||||
{
|
||||
result -= ni[i] * Ii[i] * Math.Pow(7.1 - pi, Ii[i] - 1) * Math.Pow(tau - 1.222, Ji[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gamma(tau) see also STN EN 1434-1 Annex A (A.7)
|
||||
/// </summary>
|
||||
/// <param name="pi">pi = p / p* where p* = 16.53 MPa</param>
|
||||
/// <param name="tau">tau = T* / T where T* = 1386 K</param>
|
||||
/// <returns>gamma(tau)</returns>
|
||||
static double GammaTau(double pi, double tau)
|
||||
{
|
||||
double result = 0;
|
||||
for (int i = 0; i < 34; i++)
|
||||
{
|
||||
result += ni[i] * Math.Pow(7.1 - pi, Ii[i]) * Ji[i] * Math.Pow(tau - 1.222, Ji[i] - 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conversion of measured resistance of a platinum thermometer to temperature according to ITS-90
|
||||
/// </summary>
|
||||
/// <param name="R">Measured resistance in [°C]</param>
|
||||
/// <param name="R001C">Calibrated resistance in Ohm at 0.01°C</param>
|
||||
/// <param name="a7">Calibrated ITS-90 coefficient a7</param>
|
||||
/// <param name="b7">Calibrated ITS-90 coefficient b7</param>
|
||||
/// <param name="c7">Calibrated ITS-90 coefficient c7</param>
|
||||
/// <returns>Temperature in [°C]</returns>
|
||||
public static double PlatinumResistanceTM_ITS90_R2T(double R, double R001C, double a7, double b7, double c7)
|
||||
{
|
||||
double w = R / R001C; /// ratio
|
||||
double r1 = w - 1.0;
|
||||
double dw = r1 * (a7 + r1 * (b7 + r1 * c7)); /// = a7*r1 + b7*r1^2 + c7*r1^3
|
||||
double wr = w - dw;
|
||||
double x = (wr - 2.64) / 1.64;
|
||||
|
||||
double sum = 0;
|
||||
for (int i = Di.Length - 1; i >= 0; i--)
|
||||
{
|
||||
sum = sum * x + Di[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conversion of measured resistance of a platinum thermometer to temperature using Callendar-Van Dusen equations
|
||||
/// </summary>
|
||||
/// <param name="R">Measured resistance in [°C]</param>
|
||||
/// <param name="R0">Calibrated resistance in Ohm at 0°C</param>
|
||||
/// <param name="A">Calibration coefficient a</param>
|
||||
/// <param name="B">Calibration coefficient b</param>
|
||||
/// <returns>Temperature in [°C]</returns>
|
||||
public static double PlatinumResistanceTM_ITS27_R2T(double R, double R0, double A, double B)
|
||||
{
|
||||
if (R0 * R0 * A * A - 4 * R0 * B * (R0 - R) <= 0) return 0; /// Out of range
|
||||
|
||||
return (-(R0 * A) + Math.Sqrt(R0 * R0 * A * A - 4 * R0 * B * (R0 - R))) / (2 * R0 * B);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,9 @@ namespace Config.Mappings
|
||||
Map(x => x.PressMtrUp);
|
||||
Map(x => x.PressMtrDown);
|
||||
Map(x => x.PressMtrDelta);
|
||||
//Map(x => x.ElectricMtrUp);
|
||||
//Map(x => x.ElectricMtrDown);
|
||||
//Map(x => x.ElectricMtrDelta);
|
||||
Map(x => x.StopBFValve);
|
||||
Map(x => x.ValvesOpen)
|
||||
.CustomType("StringClob")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using FluentNHibernate.Mapping;
|
||||
using Config.Entities;
|
||||
@@ -19,7 +19,7 @@ namespace Config.Mappings
|
||||
Map(x => x.LogLevel);
|
||||
Map(x => x.Parameters)
|
||||
.CustomType("StringClob")
|
||||
.CustomSqlType("varchar(8000)");
|
||||
.CustomSqlType("varchar(12000)");
|
||||
HasMany(x => x.Corrections)
|
||||
.OrderBy("Measurement")
|
||||
.Cascade.All();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
/// Copyright (c) 2013-2022 Sensus Slovensko a.s.
|
||||
///
|
||||
using FluentNHibernate.Mapping;
|
||||
using Config.Entities;
|
||||
@@ -17,12 +17,14 @@ namespace Config.Mappings
|
||||
Map(x => x.Qto);
|
||||
Map(x => x.Selector);
|
||||
Map(x => x.RegValve);
|
||||
Map(x => x.FlowMeter);
|
||||
Map(x => x.RegulMinStep).Nullable();//older databases may not have this column
|
||||
Map(x => x.FlowMeter);
|
||||
Map(x => x.PidCoef);
|
||||
Map(x => x.StartValve);
|
||||
Map(x => x.Diverter);
|
||||
Map(x => x.TempMtrDiv);
|
||||
Map(x => x.Scale);
|
||||
Map(x => x.RegVPositions);
|
||||
Map(x => x.ValvesOpen)
|
||||
.CustomType("StringClob")
|
||||
.CustomSqlType("varchar(8000)");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
/// Copyright (c) 2019-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using FluentNHibernate.Mapping;
|
||||
using Config.Entities;
|
||||
@@ -14,6 +14,7 @@ namespace Config.Mappings
|
||||
Map(x => x.ItemNr);
|
||||
Map(x => x.Name);
|
||||
Map(x => x.Part);
|
||||
Map(x => x.FlowId);
|
||||
Map(x => x.CoefQfrom);
|
||||
Map(x => x.CoefQto);
|
||||
Map(x => x.ErrLimLo);
|
||||
@@ -24,6 +25,7 @@ namespace Config.Mappings
|
||||
Map(x => x.PressLimHi);
|
||||
Map(x => x.Publish);
|
||||
Map(x => x.Evaluate);
|
||||
Map(x => x.Method);
|
||||
Map(x => x.E1);
|
||||
Map(x => x.E2);
|
||||
Map(x => x.E3);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2017 Sensus Metering Systems
|
||||
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
using FluentNHibernate.Mapping;
|
||||
using Config.Entities;
|
||||
@@ -20,7 +20,8 @@ namespace Config.Mappings
|
||||
Map(x => x.Qtg);
|
||||
Map(x => x.Qfrom);
|
||||
Map(x => x.Qto);
|
||||
Map(x => x.Volume);
|
||||
Map(x => x.IsFromToInPct);
|
||||
Map(x => x.Volume);
|
||||
Map(x => x.TestTime);
|
||||
Map(x => x.Repeats);
|
||||
Map(x => x.DoDraining);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Config
|
||||
{
|
||||
public class PurchaseResources
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
||||
Binary file not shown.
+1
-1
@@ -18,7 +18,7 @@ namespace Decrypt
|
||||
{
|
||||
if ((args.Length < 1) || !File.Exists(args[0]))
|
||||
{
|
||||
Console.WriteLine("Usage: Decode <file>");
|
||||
Console.WriteLine(@"Usage: Decode <file>");
|
||||
Console.ReadKey();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -40,9 +40,8 @@
|
||||
<StartupObject>DeviceTest.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="log4net, Version=1.2.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\log4net.2.0.2\lib\net40-full\log4net.dll</HintPath>
|
||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
+27
-2
@@ -1,3 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="2.0.15" targetFramework="net472" />
|
||||
</packages>
|
||||
+1
-1
@@ -18,7 +18,7 @@ namespace Encrypt
|
||||
{
|
||||
if ((args.Length < 1) || !File.Exists(args[0]))
|
||||
{
|
||||
Console.WriteLine("Usage: Encode <file>");
|
||||
Console.WriteLine(@"Usage: Encode <file>");
|
||||
Console.ReadKey();
|
||||
return;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -49,7 +49,7 @@
|
||||
<HintPath>..\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\packages\log4net.2.0.2\lib\net40-full\log4net.dll</HintPath>
|
||||
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data">
|
||||
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
|
||||
|
||||
@@ -5,7 +5,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
@@ -65,7 +64,8 @@ namespace GenericTest
|
||||
const int ActivityMsgsCount = 7;
|
||||
ActivityEventArgs[] activityEvents; /// Activity messages displayed in the main window
|
||||
|
||||
|
||||
Common.Forms.ModelessForm modelessForm;
|
||||
|
||||
NHibernate.ISession dbSession; /// MySQL database session
|
||||
static OracleConnection oracleConn; /// Oracle database connection (server is in Stara Tura)
|
||||
#if RF_TEST_400_900
|
||||
@@ -115,7 +115,8 @@ namespace GenericTest
|
||||
UpdateTitle();
|
||||
|
||||
/// Open a modeless form that is closed after initialization and loading the main window
|
||||
new Thread(() => Application.Run(new Common.Forms.ModelessForm("Loading workflows from a database"))).Start();
|
||||
modelessForm = new Common.Forms.ModelessForm("Loading workflows from a database");
|
||||
new Thread(() => Application.Run(modelessForm)).Start();
|
||||
|
||||
|
||||
activityEvents = new ActivityEventArgs[ActivityMsgsCount];
|
||||
@@ -159,7 +160,7 @@ namespace GenericTest
|
||||
StarSensorReading();
|
||||
}
|
||||
|
||||
Common.Forms.ModelessForm.CloseForm(); /// Close the modeless information form
|
||||
if (modelessForm != null) modelessForm.CloseForm(); /// Close the modeless information form
|
||||
}
|
||||
|
||||
private void startButton_Click(object sender, EventArgs e)
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace GenericTest
|
||||
{
|
||||
if (exc is QuitAppException)
|
||||
{
|
||||
Common.Forms.ModelessForm.CloseForm();
|
||||
//Common.Forms.ModelessForm.CloseForm();
|
||||
log.FatalFormat(Strings.Program_was_not_started_0, exc.Message);
|
||||
MessageBox.Show(exc.Message,
|
||||
Strings.Warning,
|
||||
|
||||
+27
-2
@@ -1,3 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /></startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GenesisCordonelInterface.API
|
||||
{
|
||||
public class Enums
|
||||
{
|
||||
public enum DataStorageReaderTypes : sbyte
|
||||
{
|
||||
LoginPasswordsReader,
|
||||
CalibrationParamsReader
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,967 @@
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Config;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
||||
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
|
||||
using Xylem.Common.Ui.CordonelPreadjustmentUi;
|
||||
using static GenesisCordonelInterface.API.PublicModels;
|
||||
|
||||
namespace GenesisCordonelInterface.API
|
||||
{
|
||||
/// <summary>
|
||||
/// Public-facing facade for external applications integrating with
|
||||
/// Genesis Cordonel Interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class exposes a simplified and controlled API for external callers.
|
||||
/// It validates public input, maps public request models to internal models,
|
||||
/// forwards operations to the internal GCI implementation and exposes status
|
||||
/// notifications for meter batch changes.
|
||||
///
|
||||
/// This layer should stay thin. Business logic and meter communication are
|
||||
/// handled by <see cref="InterfaceGCIToLaatzen"/>.
|
||||
/// </remarks>
|
||||
public class InterfaceOutsideToGCI
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal GCI implementation used by this public facade.
|
||||
/// </summary>
|
||||
public readonly InterfaceGCIToLaatzen _innerMeterAPI;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when meter batch status information changes.
|
||||
/// </summary>
|
||||
public event Action<List<MeterBatchDebugStatus>> MeterBatchStatusChanged;
|
||||
private readonly IMeterLoginPasswordReader loginPasswordsReader;
|
||||
private readonly IPreAdjustmentCalibrationParamsReader calibrationParamsReader;
|
||||
private readonly Core.DataStorage.Writing.CalibrationResultWriter calibrationResultWriter =
|
||||
new Core.DataStorage.Writing.CalibrationResultWriter(null);
|
||||
|
||||
/// <summary>Stores one detached completion record without accessing meter ports.</summary>
|
||||
public Task<CalibrationWriteResult> StorePreadjustmentCompletionResultAsync(
|
||||
PreadjustmentCompletionRecord record, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
if (record == null) throw new ArgumentNullException(nameof(record));
|
||||
// Capture the progress instance and slot for this write, even if a new
|
||||
// batch is initialized while the database operation is still finishing.
|
||||
var progress = _innerMeterAPI?._progressProcess;
|
||||
int? slot = record.Slot;
|
||||
Action<string> diagnostic = null;
|
||||
if (progress != null && slot.HasValue && slot.Value > 0)
|
||||
diagnostic = message => progress.DebugMessage(message, slot.Value, "DB");
|
||||
return calibrationResultWriter.StorePreadjustmentCompletionAsync(record, token, diagnostic);
|
||||
}
|
||||
|
||||
/// <summary>Creates a synthetic Completion record and exercises the real configured SQL writer.</summary>
|
||||
public async Task<CompletionProcessResult> StoreSimulatedCompletionResultAsync(
|
||||
int slot, int pcbId, bool phaseSuccess, string phaseError,
|
||||
CancellationToken token, Action<string> diagnostic)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
if (slot <= 0) throw new ArgumentOutOfRangeException(nameof(slot));
|
||||
// Synthetic fixture values belong to GCI, not to the hardware Completion process.
|
||||
var record = new PreadjustmentCompletionRecord
|
||||
{
|
||||
Slot = slot, PcbId = pcbId, MeterSize = 2,
|
||||
ZeroOffset1 = -20, ZeroOffset2 = -30, ZeroOffset3 = -67,
|
||||
FirstHitUpdatePeriod = 10, FirstHitShift = 4,
|
||||
FirstHitPercent1 = 17, FirstHitPercent2 = 13, FirstHitPercent3 = 17,
|
||||
ToFTempOffset1 = 22260, ToFTempOffset2 = -115410, ToFTempOffset3 = 14992,
|
||||
Date = DateTime.UtcNow, Successful = phaseSuccess
|
||||
};
|
||||
// Optional diagnostic subscribers must never change the storage outcome.
|
||||
try { diagnostic?.Invoke("Simulated calibration data; actual SQL write requested. Fixture MeterSize=2."); }
|
||||
catch (Exception) { }
|
||||
var write = await calibrationResultWriter.StorePreadjustmentCompletionAsync(
|
||||
record, token, diagnostic).ConfigureAwait(false);
|
||||
var result = new CompletionProcessResult
|
||||
{
|
||||
Slot = slot, Success = phaseSuccess, ProcessName = "PreAdjustment_Completion",
|
||||
ErrorMessage = phaseError
|
||||
};
|
||||
result.DatabaseRecords.Add(record);
|
||||
result.DatabaseWrites.Add(new CompletionDatabaseWriteResult { Slot = slot, Result = write });
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Stores Q3 values supplied by TBF; does not perform Q3 calibration.</summary>
|
||||
public Task<CalibrationWriteResult> StoreQ3CalibrationResultAsync(
|
||||
Q3CalibrationRecord record, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
return calibrationResultWriter.StoreQ3CalibrationAsync(record, token);
|
||||
}
|
||||
|
||||
public Task<CalibrationWriteResult> StoreQ3CalibrationResultAsync(
|
||||
Q3CalibrationRecord record, CancellationToken token, Action<string> diagnostic)
|
||||
{
|
||||
return calibrationResultWriter.StoreQ3CalibrationAsync(record, token, diagnostic);
|
||||
}
|
||||
|
||||
public Task<CalibrationWriteResult> StoreSimulatedQ3CalibrationResultAsync(
|
||||
int pcbId, CancellationToken token, Action<string> diagnostic)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
try { diagnostic?.Invoke("Simulated Q3 fixture values; actual SQL write requested."); }
|
||||
catch (Exception) { }
|
||||
return calibrationResultWriter.StoreQ3CalibrationAsync(new Q3CalibrationRecord
|
||||
{
|
||||
PcbId = pcbId, P1Offset = -0.3, P1Cal = 15260,
|
||||
P2Offset = -0.3, P2Cal = 15451, P3Offset = -0.3, P3Cal = 15204,
|
||||
Date = DateTime.UtcNow
|
||||
}, token, diagnostic);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the public GCI facade.
|
||||
/// </summary>
|
||||
public InterfaceOutsideToGCI()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the public GCI facade.
|
||||
/// </summary>
|
||||
public InterfaceOutsideToGCI(
|
||||
InterfaceGCIToLaatzen innerMeterApi,
|
||||
IMeterLoginPasswordReader passwordReader,
|
||||
IPreAdjustmentCalibrationParamsReader calibrationReader)
|
||||
: this(innerMeterApi, passwordReader, calibrationReader, null)
|
||||
{
|
||||
}
|
||||
|
||||
public InterfaceOutsideToGCI(
|
||||
InterfaceGCIToLaatzen innerMeterApi,
|
||||
IMeterLoginPasswordReader passwordReader,
|
||||
IPreAdjustmentCalibrationParamsReader calibrationReader,
|
||||
GciDataStorageConfig storageConfig)
|
||||
{
|
||||
_innerMeterAPI = innerMeterApi?? throw new ArgumentNullException(nameof(innerMeterApi));
|
||||
loginPasswordsReader = passwordReader ?? throw new ArgumentNullException(nameof(passwordReader));
|
||||
calibrationParamsReader = calibrationReader ?? throw new ArgumentNullException(nameof(calibrationReader));
|
||||
calibrationResultWriter = new Core.DataStorage.Writing.CalibrationResultWriter(storageConfig);
|
||||
|
||||
//init handlers
|
||||
//_innerMeterAPI._progressProcess.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
|
||||
}
|
||||
|
||||
private async void RequestedCalibrationParamsFromDb(
|
||||
object sender,
|
||||
EventArgsProcessProgress e)
|
||||
{
|
||||
var progress = e.Value;
|
||||
var source = progress.CancellationSource;
|
||||
var token = source.Token;
|
||||
try
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
DataQuery query = new DataQuery();
|
||||
query.QueryParams.Add(((int)e.Value.Setting.MeterSize).ToString());
|
||||
|
||||
Dictionary<string, UInt32> calibrationParams = await ReadPreAdjustmentCalibrationParamsAsync(query, token).ConfigureAwait(false);
|
||||
|
||||
lock (progress)
|
||||
{
|
||||
if (!token.IsCancellationRequested && ReferenceEquals(progress.CancellationSource, source))
|
||||
progress.PushedCalibrationParams = calibrationParams;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!token.IsCancellationRequested && ReferenceEquals(progress.CancellationSource, source))
|
||||
progress.DebugMessage($"Calibration params reading failed: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (progress)
|
||||
{
|
||||
if (!token.IsCancellationRequested && ReferenceEquals(progress.CancellationSource, source))
|
||||
progress.CalibrationParamsReadEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Laatzen ToolBox actions
|
||||
|
||||
#region ================================== PORT DETECTION ==================================
|
||||
|
||||
public PortDetectionResult DetectStreamingPort(int slot)
|
||||
{
|
||||
var result = _innerMeterAPI?.DetectStreamingPort(slot);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<PortDetectionResult> DetectStreamingPortAsync(
|
||||
int slot,
|
||||
CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var result = await _innerMeterAPI?.DetectStreamingPortAsync(slot, token);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
public PortDetectionResult DetectRequestPort(int slot)
|
||||
{
|
||||
var result = _innerMeterAPI?.DetectRequestPort(slot);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<PortDetectionResult> DetectRequestPortAsync(
|
||||
int slot,
|
||||
CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var result = await _innerMeterAPI?.DetectRequestPortAsync(slot, token);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== INIT/UPDATE/GET slot ==================================
|
||||
|
||||
/// <summary>Acquires streaming reception until the returned lease is disposed.</summary>
|
||||
public Task<IDisposable> AcquirePreadjustmentStreamingPortAsync(
|
||||
int slot, GciPortConfig streamingPort, CancellationToken token = default)
|
||||
{
|
||||
if (streamingPort == null) throw new ArgumentNullException(nameof(streamingPort));
|
||||
var mappedPort = ModelsMapping.MapPort(streamingPort);
|
||||
if (!mappedPort.HasValue) throw new ArgumentException("A streaming port is required.", nameof(streamingPort));
|
||||
return _innerMeterAPI.AcquirePreadjustmentStreamingPortAsync(slot, mappedPort.Value, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a meter slot using the provided slot configuration.
|
||||
/// </summary>
|
||||
/// <param name="request">
|
||||
/// Slot initialization request containing slot id, configuration source,
|
||||
/// password source, request port and streaming port.
|
||||
/// </param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Result describing whether the slot was created, updated, already existed or failed.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// Thrown when <paramref name="request"/> is null.
|
||||
/// </exception>
|
||||
public async Task<GciInitSlotResult> InitSlotAsync(
|
||||
GciInitSlotRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
var result = await _innerMeterAPI.InitSlotAsync(
|
||||
request.SlotId,
|
||||
ModelsMapping.MapConfigSource(request.ConfigSource),
|
||||
ModelsMapping.MapPasswordSource(request.PasswordSource),
|
||||
ModelsMapping.MapPort(request.RequestPort),
|
||||
ModelsMapping.MapPort(request.StreamingPort),
|
||||
token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates configuration of an existing meter slot.
|
||||
/// </summary>
|
||||
/// <param name="request">
|
||||
/// Slot configuration request containing updated configuration source,
|
||||
/// password source and port settings.
|
||||
/// </param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Result describing whether the slot update succeeded or failed.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// Thrown when <paramref name="request"/> is null.
|
||||
/// </exception>
|
||||
public async Task<GciInitSlotResult> UpdateSlotAsync(
|
||||
GciInitSlotRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
var result = await _innerMeterAPI.UpdateSlotAsync(
|
||||
request.SlotId,
|
||||
ModelsMapping.MapConfigSource(request.ConfigSource),
|
||||
ModelsMapping.MapPasswordSource(request.PasswordSource),
|
||||
ModelsMapping.MapPort(request.RequestPort),
|
||||
ModelsMapping.MapPort(request.StreamingPort),
|
||||
token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about one meter slot.
|
||||
/// </summary>
|
||||
/// <param name="slotId">Slot id to query. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Slot information including existence, connection state, login state,
|
||||
/// PCB id and configured communication ports.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slotId"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciSlotInfo> GetSlotAsync(
|
||||
int slotId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await _innerMeterAPI.GetOneMeterInfo(slotId, token).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about all currently initialized meter slots.
|
||||
/// </summary>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Collection of slot information records for all known meters.
|
||||
/// </returns>
|
||||
public async Task<GciAllSlotsInfo> GetAllSlotsAsync(
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var result = await _innerMeterAPI.GetAllMetersInfo(token).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans one meter slot and releases its runtime resources.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id to clean. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Result describing whether the slot cleanup succeeded or failed.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slot"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciCleanSlotResult> CleanSlotAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
var result = await _innerMeterAPI.CleanSlotAsync(slot, token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans all initialized meter slots and releases related runtime resources.
|
||||
/// </summary>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Result describing whether cleanup of all slots succeeded or failed.
|
||||
/// </returns>
|
||||
public async Task<GciCleanAllSlotsResult> CleanAllSlotsAsync(
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var result = await _innerMeterAPI.CleanAllSlotsAsync(token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================================== PASSWORD ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Sets runtime password for the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="password">Password to assign to the meter.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>Result containing password update status.</returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when slot id is invalid or password is empty.
|
||||
/// </exception>
|
||||
public async Task<GciSetPasswordResult> SetPasswordAsync(
|
||||
int slot,
|
||||
string password,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
throw new ArgumentException("Password is empty.");
|
||||
|
||||
var result = await _innerMeterAPI.SetMeterPasswordAsync(slot, password, token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== LOGIN ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Logs in to the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>Login result containing login state and status message.</returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slot"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<PublicModels.GciLoginResult> LoginOneSlotAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await _innerMeterAPI.LoginOneSlotAsync(slot, token).ConfigureAwait(false);
|
||||
return result;
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================================== CONNECTION ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Connects the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>Connection result containing connection state and status message.</returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slot"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciConnectResult> ConnectOneSlotAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await _innerMeterAPI.ConnectOneSlotAsync(slot, token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>Disconnect result containing final connection state and status message.</returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slot"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciDisconnectResult> DisconnectAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await _innerMeterAPI.DisconnectAsync(slot, token).ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================================== PCB ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Reads PCB identifier from the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>Result containing PCB id and read status.</returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="slot"/> is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciGetPcbIdResult> GetPcbIdAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await _innerMeterAPI.GetPcbIdAsync(slot, token).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================================== READ ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Reads a firmware register value from the meter assigned to the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="registerName">Register identifier to read.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Register read result containing raw register value and operation status.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when slot id or register name is invalid.
|
||||
/// </exception>
|
||||
public async Task<RegisterReadResult> ReadRegisterAsync(
|
||||
int slot,
|
||||
string registerName,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(registerName))
|
||||
throw new ArgumentException("Register name is empty.", nameof(registerName));
|
||||
|
||||
var result = await _innerMeterAPI
|
||||
.ReadRegisterAsync(slot, registerName, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== WRITE ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Writes a value to a firmware register.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="registerName">Register identifier to write.</param>
|
||||
/// <param name="value">Value to write.</param>
|
||||
/// <param name="storeToDevice">
|
||||
/// Indicates whether configuration should be permanently stored.
|
||||
/// </param>
|
||||
/// <param name="refreshSystemState">
|
||||
/// Indicates whether firmware system state should be refreshed after write.
|
||||
/// </param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Register write result describing write status.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when slot id or register name is invalid.
|
||||
/// </exception>
|
||||
public async Task<RegisterWriteResult> WriteRegisterAsync(
|
||||
int slot,
|
||||
string registerName,
|
||||
object value,
|
||||
bool storeToDevice = false,
|
||||
bool refreshSystemState = false,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(registerName))
|
||||
throw new ArgumentException("Register name is empty.", nameof(registerName));
|
||||
|
||||
var result = await _innerMeterAPI
|
||||
.WriteRegisterAsync(
|
||||
slot,
|
||||
registerName,
|
||||
value,
|
||||
storeToDevice,
|
||||
refreshSystemState,
|
||||
token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================================== Password ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Updates meter password for the specified slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id. Must be greater than zero.</param>
|
||||
/// <param name="password">New password.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>
|
||||
/// Password update result.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when slot id or password is invalid.
|
||||
/// </exception>
|
||||
public async Task<GciSetPasswordResult> SetMeterPasswordAsync(
|
||||
int slot,
|
||||
string password,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
throw new ArgumentException("Password is empty.", nameof(password));
|
||||
|
||||
var result = await _innerMeterAPI
|
||||
.SetMeterPasswordAsync(slot, password, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== DEBUG STATUS ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Gets runtime diagnostic information for all active workers.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Collection containing worker state, queue information,
|
||||
/// current operation and activity timestamps.
|
||||
/// </returns>
|
||||
public List<WorkerDebugStatus> GetWorkerDebugStatuses()
|
||||
{
|
||||
return _innerMeterAPI?.GetWorkerDebugStatuses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets runtime diagnostic information for all meter slots.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Collection containing slot state, connection state,
|
||||
/// selected state and communication configuration.
|
||||
/// </returns>
|
||||
public List<MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
|
||||
{
|
||||
return _innerMeterAPI?.GetMeterBatchDebugStatuses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises meter batch status change notification.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Intended to notify external consumers after changes in meter state.
|
||||
/// </remarks>
|
||||
public void RaiseMeterBatchStatusChanged()
|
||||
{
|
||||
var statuses = GetMeterBatchDebugStatuses();
|
||||
|
||||
var handler = MeterBatchStatusChanged;
|
||||
if (handler != null)
|
||||
handler(statuses);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== SLOT SELECTION ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Sets selection state for a slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id.</param>
|
||||
/// <param name="selected">Selection state.</param>
|
||||
public void SetSlotSelected(int slot, bool selected)
|
||||
{
|
||||
_innerMeterAPI?.SetSlotSelected(slot, selected);
|
||||
RaiseMeterBatchStatusChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified slot is selected.
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot id.</param>
|
||||
/// <returns>
|
||||
/// True if slot is selected; otherwise false.
|
||||
/// </returns>
|
||||
public bool IsSlotSelected(int slot)
|
||||
{
|
||||
return (bool)(_innerMeterAPI?.IsSlotSelected(slot));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all selected slot identifiers.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Ordered collection of selected slot ids.
|
||||
/// </returns>
|
||||
public List<int> GetSelectedSlots()
|
||||
{
|
||||
return _innerMeterAPI?.GetSelectedSlots();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== Register names ==================================
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available firmware register identifiers.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Ordered collection of register names.
|
||||
/// </returns>
|
||||
public List<string> GetAllRegisterNames()
|
||||
{
|
||||
return _innerMeterAPI?.GetAllRegisterNames();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Laatzen Preadjustment processes
|
||||
|
||||
#region ================================== PreAdjustment ==================================
|
||||
public PreAdjustmentInitializationResult Preadjustment_Initialization(
|
||||
ProcessProgress pp,
|
||||
List<MeterStateControl> mc)
|
||||
{
|
||||
//init handlers
|
||||
pp.OnRequestedCalibrationParamsFromDb -= RequestedCalibrationParamsFromDb;
|
||||
pp.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
|
||||
|
||||
return _innerMeterAPI?.Preadjustment_Initialization(pp, mc);
|
||||
}
|
||||
|
||||
public PreAdjustmentInitializationResult Preadjustment_Initialization(
|
||||
ProcessProgress pp,
|
||||
List<MeterStateControl> mc,
|
||||
CancellationToken token)
|
||||
{
|
||||
pp.OnRequestedCalibrationParamsFromDb -= RequestedCalibrationParamsFromDb;
|
||||
pp.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
|
||||
return _innerMeterAPI?.Preadjustment_Initialization(pp, mc, token);
|
||||
}
|
||||
|
||||
public void CancelPreadjustment()
|
||||
{
|
||||
_innerMeterAPI?.CancelPreadjustment();
|
||||
}
|
||||
|
||||
public Task<PreadjustmentDetectResult> PreAdjustment_DetectAsync(
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_DetectAsync(selectedSlots, token);
|
||||
}
|
||||
|
||||
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_DetectDirect(selectedSlots, token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_PreparationAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PreparationAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PreparationDirect();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect(CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PreparationDirect(token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_AmplitudeTestAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_AmplitudeTestAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_AmplitudeTestDirect();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect(CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_AmplitudeTestDirect(token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_TemperatureCalibrationAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDirect();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect(CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDirect(token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect(
|
||||
CalibrationTemperatureInput temperature, CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDirect(temperature, token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_TemperatureCalibrationAsync(
|
||||
int slot, CalibrationTemperatureInput temperature, CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationAsync(slot, temperature, token);
|
||||
}
|
||||
|
||||
public TemperatureCalibrationResult PreAdjustment_TemperatureCalibrationDetailedDirect(
|
||||
CalibrationTemperatureInput temperature, CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDetailedDirect(temperature, token);
|
||||
}
|
||||
|
||||
public Task<TemperatureCalibrationResult> PreAdjustment_TemperatureCalibrationDetailedAsync(
|
||||
int slot, CalibrationTemperatureInput temperature, CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDetailedAsync(slot, temperature, token);
|
||||
}
|
||||
|
||||
public bool PreAdjustment_PushTemperature(
|
||||
double temperature)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PushTemperature(temperature);
|
||||
}
|
||||
|
||||
public bool PreAdjustment_PushTemperature(
|
||||
double temperature,
|
||||
CancellationToken token)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
return _innerMeterAPI.PreAdjustment_PushTemperature(temperature);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_OffsetTestAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_OffsetTestAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_OffsetTestDirect();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect(CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_OffsetTestDirect(token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_CompletionAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_CompletionAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_CompletionDirect();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect(CancellationToken token)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_CompletionDirect(token);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== UNI DATA STORAGE READER ==================================
|
||||
|
||||
//LoginPasswords reading
|
||||
|
||||
/// <summary>
|
||||
/// Reads meter login password from configured GCI data storage.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing PCB ID or another configured lookup value.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token used to cancel the asynchronous operation.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
public Task<string> ReadMeterLoginPasswordAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return loginPasswordsReader.ReadMeterLoginPasswordAsync(
|
||||
query,
|
||||
token);
|
||||
}
|
||||
|
||||
//CalibrationParams reading
|
||||
|
||||
/// <summary>
|
||||
/// Reads pre-adjustment calibration parameters
|
||||
/// from configured GCI data storage.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing meter size or another configured lookup value.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token used to cancel the asynchronous operation.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary:
|
||||
///
|
||||
/// Key:
|
||||
/// Calibration parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Calibration parameter value
|
||||
/// </returns>
|
||||
public Task<Dictionary<string, UInt32>> ReadPreAdjustmentCalibrationParamsAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return calibrationParamsReader.ReadCalibrationParamsAsync(
|
||||
query,
|
||||
token);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
||||
using static GenesisCordonelInterface.API.InterfaceOutsideToGCI;
|
||||
using static GenesisCordonelInterface.API.PublicModels;
|
||||
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
|
||||
|
||||
namespace GenesisCordonelInterface.API
|
||||
{
|
||||
/// <summary>
|
||||
/// Public data contract layer for the Genesis Cordonel Interface (GCI).
|
||||
///
|
||||
/// This class defines all Data Transfer Objects (DTOs) that are exposed
|
||||
/// to external consumers (e.g. TBF, UI, or other integration layers).
|
||||
///
|
||||
/// Responsibilities:
|
||||
/// - Provide stable, dependency-free models for external usage
|
||||
/// - Decouple internal GCI implementation (GenesisMeter, Xylem libraries)
|
||||
/// from external systems
|
||||
/// - Define request/response contracts for all supported operations
|
||||
/// - Contain mapping methods between public DTOs and internal domain models
|
||||
///
|
||||
/// Architecture:
|
||||
/// External world (TBF / UI)
|
||||
/// ↓
|
||||
/// GciPublicModels (this layer)
|
||||
/// ↓
|
||||
/// Internal GCI API (InterfaceGCIToLaatzen, GenesisMeter, etc.)
|
||||
///
|
||||
/// Notes:
|
||||
/// - Public models must NOT expose internal types (e.g. GenesisMeter, IPort, etc.)
|
||||
/// - All mapping between internal and external representations must be done here
|
||||
/// - DTOs are designed to be simple, serializable, and stable over time
|
||||
/// - Any change in internal implementation should not affect these models
|
||||
///
|
||||
/// Pattern:
|
||||
/// Each operation follows a consistent structure:
|
||||
/// Request → Operation → Result
|
||||
///
|
||||
/// Example:
|
||||
/// GciInitSlotRequest → InitSlot → GciInitSlotResult
|
||||
/// GetSlot → GciSlotInfo
|
||||
/// GetPcbId → GciGetPcbIdResult
|
||||
///
|
||||
/// This layer acts as a boundary between domain logic and integration logic.
|
||||
/// </summary>
|
||||
public class ModelsMapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Mapping methods between public DTOs and internal GCI models.
|
||||
/// Ensures separation between external contracts and internal domain objects.
|
||||
/// </summary>
|
||||
#region ================================== OUTERN/INTERN and back models mapping ==================================
|
||||
public static PasswordSource MapPasswordSource(PublicModels.GciPasswordSource src)
|
||||
{
|
||||
return (PasswordSource)src;
|
||||
}
|
||||
|
||||
public static ConfigSource MapConfigSource(PublicModels.GciConfigSource src)
|
||||
{
|
||||
return (ConfigSource)src;
|
||||
}
|
||||
|
||||
public static Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig? MapPort(PublicModels.GciPortConfig port)
|
||||
{
|
||||
if (port == null)
|
||||
return null;
|
||||
|
||||
Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig result = new Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig();
|
||||
|
||||
result.PortName = port.PortName;
|
||||
result.Type = port.Type;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PublicModels.GciInitSlotResult MapInitResult(PublicModels.GciInitSlotResult result)
|
||||
{
|
||||
if (result == null)
|
||||
return null;
|
||||
|
||||
return new PublicModels.GciInitSlotResult
|
||||
{
|
||||
SlotId = result.SlotId,
|
||||
Success = result.Success,
|
||||
Message = result.Message
|
||||
};
|
||||
}
|
||||
|
||||
public static PublicModels.GciPasswordSource MapPasswordSourceBack(PasswordSource src)
|
||||
{
|
||||
return (PublicModels.GciPasswordSource)src;
|
||||
}
|
||||
|
||||
public static PublicModels.GciConfigSource MapConfigSourceBack(ConfigSource src)
|
||||
{
|
||||
return (PublicModels.GciConfigSource)src;
|
||||
}
|
||||
|
||||
public static PublicModels.GciPortConfig MapPortBack(PortConfig? port)
|
||||
{
|
||||
if (!port.HasValue)
|
||||
return null;
|
||||
|
||||
PortConfig value = port.Value;
|
||||
|
||||
return new PublicModels.GciPortConfig
|
||||
{
|
||||
PortName = value.PortName,
|
||||
Type = value.Type
|
||||
};
|
||||
}
|
||||
|
||||
public static PublicModels.GciPortConfig MapPortBack(IPort port)
|
||||
{
|
||||
if (port == null)
|
||||
return null;
|
||||
|
||||
return new PublicModels.GciPortConfig
|
||||
{
|
||||
PortName = port.GetPortName(),
|
||||
Type = port.GetType().Name
|
||||
};
|
||||
}
|
||||
|
||||
public static PublicModels.GciPortConfig MapPortBack(string portName, string portTyoe)
|
||||
{
|
||||
return new PublicModels.GciPortConfig
|
||||
{
|
||||
PortName = portName,
|
||||
Type = portTyoe
|
||||
};
|
||||
}
|
||||
|
||||
public static MeterBatchDebugStatus ToMeterBatchDebugStatus(GciSlotInfo slot)
|
||||
{
|
||||
if (slot == null)
|
||||
return null;
|
||||
|
||||
return new MeterBatchDebugStatus
|
||||
{
|
||||
Slot = slot.SlotId,
|
||||
Selected = true,
|
||||
PcbId = slot.PcbId,
|
||||
IsConnected = false,
|
||||
IsLoggedOn = false,
|
||||
RequestPort = slot.RequestPort == null ? "" : slot.RequestPort.PortName,
|
||||
StreamingPort = slot.StreamingPort == null ? "" : slot.StreamingPort.PortName,
|
||||
FwVersion = "",
|
||||
InterfaceVersion = ""
|
||||
};
|
||||
}
|
||||
|
||||
public static List<MeterBatchDebugStatus> ToMeterBatchDebugStatusList(
|
||||
IEnumerable<GciSlotInfo> slots)
|
||||
{
|
||||
if (slots == null)
|
||||
return new List<MeterBatchDebugStatus>();
|
||||
|
||||
return slots
|
||||
.Where(x => x != null)
|
||||
.Select(ToMeterBatchDebugStatus)
|
||||
.ToList();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,636 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
||||
using static GenesisCordonelInterface.API.InterfaceOutsideToGCI;
|
||||
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
|
||||
|
||||
namespace GenesisCordonelInterface.API
|
||||
{
|
||||
/// <summary>
|
||||
/// Public data contract layer for the Genesis Cordonel Interface (GCI).
|
||||
///
|
||||
/// This class defines all Data Transfer Objects (DTOs) that are exposed
|
||||
/// to external consumers (e.g. TBF, UI, or other integration layers).
|
||||
///
|
||||
/// Responsibilities:
|
||||
/// - Provide stable, dependency-free models for external usage
|
||||
/// - Decouple internal GCI implementation (GenesisMeter, Xylem libraries)
|
||||
/// from external systems
|
||||
/// - Define request/response contracts for all supported operations
|
||||
/// - Contain mapping methods between public DTOs and internal domain models
|
||||
///
|
||||
/// Architecture:
|
||||
/// External world (TBF / UI)
|
||||
/// ↓
|
||||
/// GciPublicModels (this layer)
|
||||
/// ↓
|
||||
/// Internal GCI API (InterfaceGCIToLaatzen, GenesisMeter, etc.)
|
||||
///
|
||||
/// Notes:
|
||||
/// - Public models must NOT expose internal types (e.g. GenesisMeter, IPort, etc.)
|
||||
/// - All mapping between internal and external representations must be done here
|
||||
/// - DTOs are designed to be simple, serializable, and stable over time
|
||||
/// - Any change in internal implementation should not affect these models
|
||||
///
|
||||
/// Pattern:
|
||||
/// Each operation follows a consistent structure:
|
||||
/// Request → Operation → Result
|
||||
///
|
||||
/// Example:
|
||||
/// GciInitSlotRequest → InitSlot → GciInitSlotResult
|
||||
/// GetSlot → GciSlotInfo
|
||||
/// GetPcbId → GciGetPcbIdResult
|
||||
///
|
||||
/// This layer acts as a boundary between domain logic and integration logic.
|
||||
/// </summary>
|
||||
public class PublicModels
|
||||
{
|
||||
/// <summary>Persisted values for one meter and one preadjustment attempt.</summary>
|
||||
public sealed class PreadjustmentCompletionRecord
|
||||
{
|
||||
// Diagnostic routing only. Not a database column or SQL parameter.
|
||||
public int? Slot { get; set; }
|
||||
public int PcbId { get; set; }
|
||||
public int? MeterSize { get; set; }
|
||||
public int? ZeroOffset1 { get; set; }
|
||||
public int? ZeroOffset2 { get; set; }
|
||||
public int? ZeroOffset3 { get; set; }
|
||||
public int? FirstHitUpdatePeriod { get; set; }
|
||||
public int? FirstHitShift { get; set; }
|
||||
public int? FirstHitPercent1 { get; set; }
|
||||
public int? FirstHitPercent2 { get; set; }
|
||||
public int? FirstHitPercent3 { get; set; }
|
||||
public int? ToFTempOffset1 { get; set; }
|
||||
public int? ToFTempOffset2 { get; set; }
|
||||
public int? ToFTempOffset3 { get; set; }
|
||||
// Timestamp of the attempt, not the time of a possible later write retry.
|
||||
public DateTime Date { get; set; }
|
||||
public bool Successful { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Q3 values calculated and confirmed by the caller; no port access.</summary>
|
||||
public sealed class Q3CalibrationRecord
|
||||
{
|
||||
public int PcbId { get; set; }
|
||||
// Preserve the existing TBF meaning/unit of each offset (do not rescale here).
|
||||
public double? P1Offset { get; set; }
|
||||
public int? P1Cal { get; set; }
|
||||
public double? P2Offset { get; set; }
|
||||
public int? P2Cal { get; set; }
|
||||
public double? P3Offset { get; set; }
|
||||
public int? P3Cal { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Completion outcome plus detached SQL inputs and separate write outcomes.</summary>
|
||||
public sealed class CompletionProcessResult : PreAdjustmentProcessResult
|
||||
{
|
||||
public List<PreadjustmentCompletionRecord> DatabaseRecords { get; set; } =
|
||||
new List<PreadjustmentCompletionRecord>();
|
||||
public List<CompletionDatabaseWriteResult> DatabaseWrites { get; set; } =
|
||||
new List<CompletionDatabaseWriteResult>();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString() + ", SQL=[" + string.Join("; ",
|
||||
DatabaseWrites.Select(w => "Slot=" + w.Slot + ", " + w.Result.Status)) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CompletionDatabaseWriteResult
|
||||
{
|
||||
public int Slot { get; set; }
|
||||
public CalibrationWriteResult Result { get; set; }
|
||||
}
|
||||
|
||||
public enum CalibrationWriteStatus
|
||||
{
|
||||
Failed = 0, Stored = 1, Disabled = 2, Simulated = 3,
|
||||
// The connection failed during commit; verify the DB before retrying.
|
||||
OutcomeUnknown = 4
|
||||
}
|
||||
|
||||
/// <summary>Database outcome, independent of the physical calibration outcome.</summary>
|
||||
public sealed class CalibrationWriteResult
|
||||
{
|
||||
public CalibrationWriteStatus Status { get; set; }
|
||||
public bool Success { get { return Status == CalibrationWriteStatus.Stored; } }
|
||||
public int PcbId { get; set; }
|
||||
public long? RecordId { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Status={0}, PcbId={1}, RecordId={2}, Error={3}",
|
||||
Status, PcbId, RecordId, ErrorMessage ?? "None");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HideSensitiveValues { get; set; } = true;
|
||||
|
||||
private static string FormatPassword(string password)
|
||||
{
|
||||
if (!HideSensitiveValues)
|
||||
return password ?? "<null>";
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
return "<empty>";
|
||||
|
||||
return "********";
|
||||
}
|
||||
/// <summary>
|
||||
/// Public DTOs exposed to external systems.
|
||||
/// These models represent the contract of the GCI API.
|
||||
/// They must remain stable and independent of internal implementation.
|
||||
/// </summary>
|
||||
#region ================================== PUBLIC MODELS ===========================================
|
||||
|
||||
public class RegisterReadResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string RegisterName { get; set; }
|
||||
public string RawHex { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"Success={0}, RegisterName={1}, RawHex={2}, ErrorMessage={3}",
|
||||
Success,
|
||||
RegisterName,
|
||||
RawHex,
|
||||
ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public class WorkerDebugStatus
|
||||
{
|
||||
public int Slot { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int QueueLength { get; set; }
|
||||
public bool IsBusy { get; set; }
|
||||
public string CurrentOperation { get; set; }
|
||||
public string LastError { get; set; }
|
||||
public DateTime LastActivity { get; set; }
|
||||
}
|
||||
|
||||
public class MeterBatchDebugStatus
|
||||
{
|
||||
public int Slot { get; set; }
|
||||
public bool Selected { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public bool IsConnected { get; set; }
|
||||
public bool IsLoggedOn { get; set; }
|
||||
public string RequestPort { get; set; }
|
||||
public string StreamingPort { get; set; }
|
||||
public string RequestPortType { get; set; }
|
||||
public string FwVersion { get; set; }
|
||||
public string InterfaceVersion { get; set; }
|
||||
}
|
||||
|
||||
public class RegisterWriteResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string RegisterName { get; set; }
|
||||
public object WrittenValue { get; set; }
|
||||
public bool StoreToDevice { get; set; }
|
||||
public bool RefreshSystemState { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Success={Success}, " +
|
||||
$"Register={RegisterName ?? "<null>"}, " +
|
||||
$"Value={WrittenValue ?? "<null>"}, " +
|
||||
$"StoreToDevice={StoreToDevice}, " +
|
||||
$"RefreshSystemState={RefreshSystemState}, " +
|
||||
$"Error={ErrorMessage ?? "<none>"}";
|
||||
}
|
||||
}
|
||||
|
||||
public class PortDetectionResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int Slot { get; set; }
|
||||
public string PortName { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"Slot={0}, Success={1}, PortName={2}, PcbId={3}, ErrorMessage={4}",
|
||||
Slot,
|
||||
Success,
|
||||
PortName,
|
||||
PcbId,
|
||||
ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciSlotInfo
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Exists { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public bool IsConnected { get; set; }
|
||||
public bool IsLoggedOn { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public string Password { get; set; }
|
||||
public GciConfigSource ConfigSource { get; set; }
|
||||
public GciPasswordSource PasswordSource { get; set; }
|
||||
public GciPortConfig RequestPort { get; set; }
|
||||
public GciPortConfig StreamingPort { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Exists={1}, Success={2}, IsConnected={3}, IsLoggedOn={4}, Message={5}, PcbId={6}, Password={7}, ConfigSource={8}, PasswordSource={9}, RequestPort={10}, StreamingPort={11}",
|
||||
SlotId,
|
||||
Exists,
|
||||
Success,
|
||||
IsConnected,
|
||||
IsLoggedOn,
|
||||
Message,
|
||||
PcbId,
|
||||
FormatPassword(Password),
|
||||
ConfigSource,
|
||||
PasswordSource,
|
||||
RequestPort,
|
||||
StreamingPort);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciAllSlotsInfo
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public List<GciSlotInfo> Slots { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Success={Success}, Count={Slots?.Count ?? 0}, Message={Message}";
|
||||
}
|
||||
}
|
||||
|
||||
public class Result
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, Message={2}",
|
||||
SlotId,
|
||||
Success,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
|
||||
public enum GciPasswordSource
|
||||
{
|
||||
RestApi = 0,
|
||||
OfflineFile = 1,
|
||||
InterfaceInputPassword = 2,
|
||||
}
|
||||
public enum GciConfigSource
|
||||
{
|
||||
FileConfig = 0,
|
||||
InterfaceInputConfig = 1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection of port settings
|
||||
/// </summary>
|
||||
public class GciPortConfig
|
||||
{
|
||||
public string PortName { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("PortName={0}, Type={1}", PortName, Type);
|
||||
}
|
||||
}
|
||||
|
||||
public static GciPortConfig CreatePortConfig(string portName, string type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(portName))
|
||||
return null;
|
||||
|
||||
return new GciPortConfig
|
||||
{
|
||||
PortName = portName,
|
||||
Type = MapPortType(type)
|
||||
};
|
||||
}
|
||||
|
||||
public static string MapPortType(string type)
|
||||
{
|
||||
switch ((type ?? "").Trim().ToUpperInvariant())
|
||||
{
|
||||
case "RFID":
|
||||
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.RfidSerialPort";
|
||||
|
||||
case "UART":
|
||||
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.UartSerialPort";
|
||||
|
||||
case "IRDA":
|
||||
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.IrdaSerialPort";
|
||||
|
||||
default:
|
||||
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.IrdaSerialPort";
|
||||
}
|
||||
}
|
||||
|
||||
public class GciInitSlotRequest
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public GciConfigSource ConfigSource { get; set; }
|
||||
public GciPasswordSource PasswordSource { get; set; }
|
||||
public GciPortConfig RequestPort { get; set; }
|
||||
public GciPortConfig StreamingPort { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, GciConfigSource={1}, PasswordSource={2}, RequestPort={3}, StreamingPort={4}, Password={5}",
|
||||
SlotId,
|
||||
ConfigSource,
|
||||
PasswordSource,
|
||||
RequestPort,
|
||||
StreamingPort,
|
||||
FormatPassword(Password));
|
||||
}
|
||||
}
|
||||
|
||||
public class GciInitSlotResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
|
||||
public string PcbId { get; set; }
|
||||
|
||||
public bool Created { get; set; }
|
||||
|
||||
public bool Updated { get; set; }
|
||||
|
||||
public bool AlreadyExists { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, Message={2}, PcbId={3}, Created={4}, Updated={5}, AlreadyExists={6}",
|
||||
SlotId,
|
||||
Success,
|
||||
Message,
|
||||
PcbId,
|
||||
Created,
|
||||
Updated,
|
||||
AlreadyExists);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciCleanAllSlotsResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"Success={0}, Message={1}",
|
||||
Success,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
public class GciCleanSlotResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, Message={2}",
|
||||
SlotId,
|
||||
Success,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciGetPcbIdResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public string Message { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, PcbId={2}, Message={3}",
|
||||
SlotId,
|
||||
Success,
|
||||
PcbId,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
public class GciConnectResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public bool IsConnected { get; set; }
|
||||
public string Message { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, PcbId={2}, IsConnected={3}, Message={4}",
|
||||
SlotId,
|
||||
Success,
|
||||
PcbId,
|
||||
IsConnected,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciLoginResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string PcbId { get; set; }
|
||||
public bool IsLoggedOn { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Slot={SlotId}, Success={Success}, PcbId={PcbId}, IsLoggedOn={IsLoggedOn}, Message={Message ?? "<none>"}";
|
||||
}
|
||||
}
|
||||
|
||||
public class GciRegisterSnapshot
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string RawValue { get; set; }
|
||||
public string Min { get; set; }
|
||||
public string Max { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string IsAvailable { get; set; }
|
||||
public string Privilege { get; set; }
|
||||
}
|
||||
|
||||
public class GciDisconnectResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, Message={2}",
|
||||
SlotId,
|
||||
Success,
|
||||
Message);
|
||||
}
|
||||
}
|
||||
|
||||
public class GciSetPasswordResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"SlotId={0}, Success={1}, Password={2}, Message={3}",
|
||||
SlotId,
|
||||
Success,
|
||||
FormatPassword(Password),
|
||||
Message);
|
||||
}
|
||||
}
|
||||
|
||||
public class PreAdjustmentProcessResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int Slot { get; set; }
|
||||
public string ProcessName { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Success={Success}, " +
|
||||
$"Slot={Slot}, " +
|
||||
$"Process={ProcessName}, " +
|
||||
$"Error={ErrorMessage ?? "None"}";
|
||||
}
|
||||
}
|
||||
|
||||
public class TemperatureCalibrationSlotResult : PreAdjustmentProcessResult
|
||||
{
|
||||
public decimal? ReferenceTemperatureCelsius { get; set; }
|
||||
public decimal? MeterTemperatureCelsius { get; set; }
|
||||
public decimal? AbsoluteDifferenceCelsius { get; set; }
|
||||
// The effective existing process limit, reported for diagnostics only.
|
||||
public decimal? DeviationLimitCelsius { get; set; }
|
||||
public int SampleCount { get; set; }
|
||||
public bool? TemperatureCheckPassed { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var culture = System.Globalization.CultureInfo.InvariantCulture;
|
||||
return base.ToString() + string.Format(culture,
|
||||
", Reference={0} C, Meter={1} C, Difference={2} C, Limit={3} C, Samples={4}, Check={5}",
|
||||
ReferenceTemperatureCelsius?.ToString(culture) ?? "N/A",
|
||||
MeterTemperatureCelsius?.ToString(culture) ?? "N/A",
|
||||
AbsoluteDifferenceCelsius?.ToString(culture) ?? "N/A",
|
||||
DeviationLimitCelsius?.ToString(culture) ?? "N/A", SampleCount,
|
||||
TemperatureCheckPassed.HasValue ? (TemperatureCheckPassed.Value ? "PASSED" : "FAILED") : "NOT_EVALUATED");
|
||||
}
|
||||
}
|
||||
|
||||
public class TemperatureCalibrationResult : PreAdjustmentProcessResult
|
||||
{
|
||||
public List<TemperatureCalibrationSlotResult> Slots { get; set; } =
|
||||
new List<TemperatureCalibrationSlotResult>();
|
||||
public bool IsSimulated { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString() + ", Simulated=" + IsSimulated +
|
||||
", TemperatureResults=[" + string.Join("; ", Slots.Select(s => s.ToString())) + "]";
|
||||
}
|
||||
|
||||
// Preserve status for failures before process creation and for simulation.
|
||||
// Missing measurements must never be represented as a measured zero.
|
||||
public static TemperatureCalibrationResult FromProcessResult(
|
||||
PreAdjustmentProcessResult result, bool simulated = false)
|
||||
{
|
||||
if (result == null) throw new ArgumentNullException(nameof(result));
|
||||
var detailed = result as TemperatureCalibrationResult;
|
||||
if (detailed != null) return detailed;
|
||||
return new TemperatureCalibrationResult
|
||||
{
|
||||
Success = result.Success, Slot = result.Slot, ProcessName = result.ProcessName,
|
||||
ErrorMessage = result.ErrorMessage, IsSimulated = simulated
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class PreadjustmentDetectResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int DetectedMeterCount { get; set; }
|
||||
public int DetectedThermometerCount { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Success={Success}, " +
|
||||
$"Meters={DetectedMeterCount}, " +
|
||||
$"Thermometers={DetectedThermometerCount}, " +
|
||||
$"Error={ErrorMessage ?? "None"}";
|
||||
}
|
||||
}
|
||||
|
||||
public class PreAdjustmentInitializationResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Slots { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Success={Success}, " +
|
||||
$"Slots={Slots}, " +
|
||||
$"Error={ErrorMessage ?? "None"}";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Xylem.Common.CommonCore" publicKeyToken="null" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.18.17954" newVersion="2.8.18.17954" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user