├── res
└── icon.png
├── requirements.txt
├── README.md
├── remotedevice.ui
├── dms.ui
└── dms.py
/res/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenIPC/dms/master/res/icon.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | netifaces==0.11.0
2 | PyQt5==5.15.9
3 | python_dvr==0.0.1
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Device Management System [][telegram]
2 |
3 |
4 | ### Installation
5 |
6 | ```
7 | git clone https://github.com/OpenIPC/dms.git
8 | cd dms
9 | pip3 install --upgrade pip
10 | pip3 install -r ./requirements.txt
11 | ```
12 |
13 | ### Run project
14 |
15 | ```
16 | python3 ./dms.py
17 | ```
18 |
19 |
20 | More information about the [project][project] is available in our [website][website] and on the [wiki][wiki].
21 |
22 |
23 |
24 |
25 |
26 |
27 | [firmware]: https://github.com/openipc/firmware/
28 | [mit]: https://opensource.org/license/mit/
29 | [opencollective]: https://opencollective.com/openipc
30 | [paypal]: https://www.paypal.com/donate/?hosted_button_id=C6F7UJLA58MBS
31 | [project]: https://github.com/openipc/
32 | [telegram]: https://t.me/OpenIPC
33 | [website]: https://openipc.org/
34 | [wiki]: https://github.com/openipc/wiki/
35 |
--------------------------------------------------------------------------------
/remotedevice.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | DigitalChannels
4 |
5 |
6 |
7 | 0
8 | 0
9 | 882
10 | 721
11 |
12 |
13 |
14 | Digital Channels
15 |
16 |
17 |
18 | res/icon.pngres/icon.png
19 |
20 |
21 |
22 |
23 | 5
24 | 305
25 | 88
26 | 25
27 |
28 |
29 |
30 | Local Search
31 |
32 |
33 |
34 |
35 |
36 | 195
37 | 305
38 | 88
39 | 25
40 |
41 |
42 |
43 | Add all
44 |
45 |
46 |
47 |
48 |
49 | 0
50 | 0
51 | 881
52 | 305
53 |
54 |
55 |
56 | false
57 |
58 |
59 | QAbstractItemView::NoEditTriggers
60 |
61 |
62 | true
63 |
64 |
65 | QAbstractItemView::DragOnly
66 |
67 |
68 | Qt::LinkAction
69 |
70 |
71 | true
72 |
73 |
74 | QAbstractItemView::SingleSelection
75 |
76 |
77 | QAbstractItemView::SelectRows
78 |
79 |
80 | false
81 |
82 |
83 | false
84 |
85 |
86 | 1
87 |
88 |
89 |
90 |
91 | IP Address
92 |
93 |
94 |
95 |
96 | Port
97 |
98 |
99 |
100 |
101 | MAC Address
102 |
103 |
104 |
105 |
106 | CloudID
107 |
108 |
109 |
110 |
111 | Name
112 |
113 |
114 |
115 |
116 | Chan
117 |
118 |
119 |
120 |
121 | Type
122 |
123 |
124 |
125 |
126 |
127 |
128 | 0
129 | 330
130 | 881
131 | 301
132 |
133 |
134 |
135 | true
136 |
137 |
138 | QFrame::StyledPanel
139 |
140 |
141 | QFrame::Sunken
142 |
143 |
144 | QAbstractScrollArea::AdjustIgnored
145 |
146 |
147 | false
148 |
149 |
150 | false
151 |
152 |
153 | false
154 |
155 |
156 | QAbstractItemView::NoDragDrop
157 |
158 |
159 | Qt::LinkAction
160 |
161 |
162 | true
163 |
164 |
165 | QAbstractItemView::SingleSelection
166 |
167 |
168 | QAbstractItemView::SelectRows
169 |
170 |
171 | false
172 |
173 |
174 | false
175 |
176 |
177 | false
178 |
179 |
180 | 1
181 |
182 |
183 | 25
184 |
185 |
186 | false
187 |
188 |
189 |
190 |
191 | #
192 |
193 |
194 |
195 |
196 | Title
197 |
198 |
199 |
200 |
201 | IP Address
202 |
203 |
204 |
205 |
206 | Port
207 |
208 |
209 |
210 |
211 | SyncRes
212 |
213 |
214 |
215 |
216 | SyncTime
217 |
218 |
219 |
220 |
221 | Delay
222 |
223 |
224 |
225 |
226 | Chan
227 |
228 |
229 |
230 |
231 | Proto
232 |
233 |
234 |
235 |
236 | Username
237 |
238 |
239 |
240 |
241 | Password
242 |
243 |
244 | -
245 |
246 |
247 |
248 |
249 | ItemIsSelectable|ItemIsDragEnabled|ItemIsDropEnabled|ItemIsUserCheckable|ItemIsEnabled
250 |
251 |
252 |
253 |
254 |
255 |
256 | 100
257 | 305
258 | 88
259 | 25
260 |
261 |
262 | -
263 |
264 | NETIP
265 |
266 |
267 | -
268 |
269 | ONVIF
270 |
271 |
272 |
273 |
274 |
275 |
276 | 195
277 | 635
278 | 88
279 | 25
280 |
281 |
282 |
283 | CAM
284 |
285 |
286 | channel name
287 |
288 |
289 |
290 |
291 |
292 | 5
293 | 635
294 | 88
295 | 25
296 |
297 |
298 |
299 | admin
300 |
301 |
302 |
303 |
304 |
305 | 100
306 | 635
307 | 88
308 | 25
309 |
310 |
311 |
312 |
313 |
314 |
315 | password
316 |
317 |
318 |
319 |
320 |
321 | 5
322 | 665
323 | 88
324 | 25
325 |
326 |
327 |
328 | All
329 |
330 |
331 |
332 |
333 |
334 | 100
335 | 665
336 | 88
337 | 25
338 |
339 |
340 |
341 | All
342 |
343 |
344 |
345 |
346 |
347 | 195
348 | 665
349 | 88
350 | 25
351 |
352 |
353 |
354 | All
355 |
356 |
357 |
358 |
359 |
360 | 290
361 | 635
362 | 88
363 | 25
364 |
365 |
366 | -
367 |
368 | False
369 |
370 |
371 | -
372 |
373 | True
374 |
375 |
376 |
377 |
378 |
379 |
380 | 385
381 | 635
382 | 88
383 | 25
384 |
385 |
386 |
387 | T&Z
388 |
389 |
390 | 3
391 |
392 |
393 | true
394 |
395 | -
396 |
397 | OFF
398 |
399 |
400 | -
401 |
402 | UTC
403 |
404 |
405 | -
406 |
407 | Local
408 |
409 |
410 | -
411 |
412 | T&Z
413 |
414 |
415 |
416 |
417 |
418 |
419 | 480
420 | 635
421 | 88
422 | 25
423 |
424 |
425 |
426 | 2
427 |
428 | -
429 |
430 | 150
431 |
432 |
433 | -
434 |
435 | 250
436 |
437 |
438 | -
439 |
440 | 333
441 |
442 |
443 | -
444 |
445 | 667
446 |
447 |
448 | -
449 |
450 | 1000
451 |
452 |
453 | -
454 |
455 | 2000
456 |
457 |
458 | -
459 |
460 | 3000
461 |
462 |
463 |
464 |
465 |
466 |
467 | 290
468 | 665
469 | 88
470 | 25
471 |
472 |
473 |
474 | All
475 |
476 |
477 |
478 |
479 |
480 | 385
481 | 665
482 | 88
483 | 25
484 |
485 |
486 |
487 | All
488 |
489 |
490 |
491 |
492 |
493 | 480
494 | 665
495 | 88
496 | 25
497 |
498 |
499 |
500 | All
501 |
502 |
503 |
504 |
505 |
506 | 790
507 | 695
508 | 88
509 | 25
510 |
511 |
512 |
513 | Cancel
514 |
515 |
516 |
517 |
518 |
519 | 695
520 | 695
521 | 88
522 | 25
523 |
524 |
525 |
526 | &Save
527 |
528 |
529 |
530 |
531 |
532 |
533 |
--------------------------------------------------------------------------------
/dms.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 | true
7 |
8 |
9 |
10 | 0
11 | 0
12 | 1024
13 | 681
14 |
15 |
16 |
17 | DMS
18 |
19 |
20 |
21 | res/icon.pngres/icon.png
22 |
23 |
24 |
25 | 16
26 | 16
27 |
28 |
29 |
30 | Qt::ToolButtonIconOnly
31 |
32 |
33 |
34 |
35 |
36 | 20
37 | 590
38 | 75
39 | 25
40 |
41 |
42 |
43 | &Search
44 |
45 |
46 |
47 |
48 |
49 | 0
50 | 40
51 | 631
52 | 545
53 |
54 |
55 |
56 |
57 | 0
58 | 0
59 |
60 |
61 |
62 | false
63 |
64 |
65 | QAbstractItemView::NoEditTriggers
66 |
67 |
68 | false
69 |
70 |
71 | true
72 |
73 |
74 | QAbstractItemView::SelectRows
75 |
76 |
77 | true
78 |
79 |
80 | false
81 |
82 |
83 | false
84 |
85 |
86 | 1
87 |
88 |
89 | 8
90 |
91 |
92 | true
93 |
94 |
95 | 25
96 |
97 |
98 | 90
99 |
100 |
101 | false
102 |
103 |
104 | false
105 |
106 |
107 | true
108 |
109 |
110 | false
111 |
112 |
113 | 30
114 |
115 |
116 | 30
117 |
118 |
119 |
120 |
121 | #
122 |
123 |
124 | AlignCenter
125 |
126 |
127 |
128 |
129 | IP
130 |
131 |
132 |
133 |
134 | Port
135 |
136 |
137 |
138 |
139 | MAC
140 |
141 |
142 |
143 |
144 | CloudID
145 |
146 |
147 |
148 |
149 | Version
150 |
151 |
152 |
153 |
154 | Date
155 |
156 |
157 |
158 |
159 | Name
160 |
161 |
162 |
163 |
164 |
165 |
166 | 10
167 | 10
168 | 101
169 | 25
170 |
171 |
172 |
173 | admin
174 |
175 |
176 |
177 |
178 |
179 | 120
180 | 10
181 | 110
182 | 25
183 |
184 |
185 |
186 |
187 |
188 |
189 | password
190 |
191 |
192 |
193 |
194 |
195 | 240
196 | 10
197 | 110
198 | 25
199 |
200 |
201 |
202 | newpassword
203 |
204 |
205 |
206 |
207 |
208 | 360
209 | 10
210 | 75
211 | 25
212 |
213 |
214 |
215 | &Change
216 |
217 |
218 |
219 |
220 |
221 | 440
222 | 10
223 | 110
224 | 25
225 |
226 |
227 |
228 | 000.000.000.000
229 |
230 |
231 | 0.0.0.0
232 |
233 |
234 | 15
235 |
236 |
237 | Qt::AlignCenter
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 | 555
247 | 10
248 | 75
249 | 25
250 |
251 |
252 |
253 | AutoIP
254 |
255 |
256 |
257 |
258 |
259 | 635
260 | 10
261 | 260
262 | 25
263 |
264 |
265 |
266 | Host interface
267 |
268 |
269 |
270 |
271 |
272 | 900
273 | 10
274 | 116
275 | 25
276 |
277 |
278 |
279 | QComboBox::InsertAtCurrent
280 |
281 |
282 | Host IP
283 |
284 |
285 | false
286 |
287 |
288 |
289 |
290 | false
291 |
292 |
293 |
294 | 105
295 | 590
296 | 75
297 | 25
298 |
299 |
300 |
301 | &Add IP
302 |
303 |
304 |
305 |
306 |
307 | 635
308 | 40
309 | 380
310 | 545
311 |
312 |
313 |
314 | 1
315 |
316 |
317 |
318 | System
319 |
320 |
321 |
322 |
323 | Network
324 |
325 |
326 |
327 |
328 | 0
329 | 0
330 | 370
331 | 170
332 |
333 |
334 |
335 | QFrame::Box
336 |
337 |
338 | QFrame::Raised
339 |
340 |
341 | 1
342 |
343 |
344 |
345 |
346 | 85
347 | 135
348 | 110
349 | 25
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | 000.000.000.000
363 |
364 |
365 | 0.0.0.0
366 |
367 |
368 | 15
369 |
370 |
371 | true
372 |
373 |
374 | Qt::AlignCenter
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 | 5
384 | 110
385 | 76
386 | 18
387 |
388 |
389 |
390 | DNS1
391 |
392 |
393 |
394 |
395 |
396 | 5
397 | 75
398 | 76
399 | 18
400 |
401 |
402 |
403 | Gateway
404 |
405 |
406 |
407 |
408 |
409 | 85
410 | 70
411 | 110
412 | 25
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 | 000.000.000.000
426 |
427 |
428 | 0.0.0.0
429 |
430 |
431 | 15
432 |
433 |
434 | true
435 |
436 |
437 | Qt::AlignCenter
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 | 85
447 | 40
448 | 110
449 | 25
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 | 000.000.000.000
463 |
464 |
465 | 255.255.255.0
466 |
467 |
468 | 15
469 |
470 |
471 | true
472 |
473 |
474 | Qt::AlignCenter
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 | false
483 |
484 |
485 |
486 | 205
487 | 70
488 | 155
489 | 25
490 |
491 |
492 |
493 | Public DNS
494 |
495 |
496 |
497 |
498 |
499 | 85
500 | 10
501 | 110
502 | 25
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 | 000.000.000.000
516 |
517 |
518 | 000.000.000.000
519 |
520 |
521 | 15
522 |
523 |
524 | true
525 |
526 |
527 | Qt::AlignCenter
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 | 5
537 | 140
538 | 76
539 | 18
540 |
541 |
542 |
543 | DNS2
544 |
545 |
546 |
547 |
548 |
549 | 5
550 | 15
551 | 76
552 | 18
553 |
554 |
555 |
556 | IP Address
557 |
558 |
559 |
560 |
561 |
562 | 5
563 | 45
564 | 76
565 | 18
566 |
567 |
568 |
569 | Subnet
570 |
571 |
572 |
573 |
574 | false
575 |
576 |
577 |
578 | 205
579 | 40
580 | 155
581 | 25
582 |
583 |
584 |
585 | IP+1
586 |
587 |
588 |
589 |
590 | false
591 |
592 |
593 |
594 | 205
595 | 10
596 | 155
597 | 25
598 |
599 |
600 |
601 | Defaults
602 |
603 |
604 |
605 |
606 |
607 | 85
608 | 105
609 | 110
610 | 25
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 | 000.000.000.000
624 |
625 |
626 | 0.0.0.0
627 |
628 |
629 | 15
630 |
631 |
632 | true
633 |
634 |
635 | Qt::AlignCenter
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 | true
644 |
645 |
646 |
647 | 205
648 | 135
649 | 155
650 | 25
651 |
652 |
653 |
654 | Digital Channels
655 |
656 |
657 |
658 |
659 |
660 |
661 | 0
662 | 170
663 | 371
664 | 70
665 |
666 |
667 |
668 | QFrame::StyledPanel
669 |
670 |
671 | QFrame::Raised
672 |
673 |
674 |
675 |
676 | 5
677 | 5
678 | 111
679 | 22
680 |
681 |
682 |
683 | Upgrade
684 |
685 |
686 |
687 |
688 |
689 | 5
690 | 25
691 | 111
692 | 22
693 |
694 |
695 |
696 | AutoUpgrade
697 |
698 |
699 |
700 |
701 |
702 | 5
703 | 45
704 | 111
705 | 22
706 |
707 |
708 |
709 | NTP
710 |
711 |
712 |
713 |
714 |
715 | 115
716 | 5
717 | 111
718 | 22
719 |
720 |
721 |
722 | SmartNet
723 |
724 |
725 |
726 |
727 |
728 | 115
729 | 25
730 | 111
731 | 22
732 |
733 |
734 |
735 | IPChange
736 |
737 |
738 |
739 |
740 |
741 | 115
742 | 45
743 | 111
744 | 22
745 |
746 |
747 |
748 | AutoAdd
749 |
750 |
751 |
752 |
753 |
754 | 200
755 | 5
756 | 111
757 | 22
758 |
759 |
760 |
761 | Cloud
762 |
763 |
764 |
765 |
766 |
767 | 200
768 | 45
769 | 111
770 | 22
771 |
772 |
773 |
774 | ONVIF Auth
775 |
776 |
777 |
778 |
779 |
780 | 200
781 | 25
782 | 111
783 | 22
784 |
785 |
786 |
787 | RTSP
788 |
789 |
790 |
791 |
792 |
793 |
794 | Encode
795 |
796 |
797 |
798 |
799 | Settings
800 |
801 |
802 |
803 |
804 | 5
805 | 5
806 | 116
807 | 26
808 |
809 |
810 |
811 |
812 |
813 |
814 | Language
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 | 445
823 | 590
824 | 75
825 | 25
826 |
827 |
828 |
829 | Upgrade
830 |
831 |
832 |
833 |
834 |
835 | 275
836 | 590
837 | 75
838 | 25
839 |
840 |
841 |
842 | Reboot
843 |
844 |
845 |
846 |
847 | false
848 |
849 |
850 |
851 | 360
852 | 590
853 | 75
854 | 25
855 |
856 |
857 |
858 | Export
859 |
860 |
861 |
862 |
863 | false
864 |
865 |
866 |
867 | 190
868 | 590
869 | 75
870 | 25
871 |
872 |
873 |
874 | Add ID
875 |
876 |
877 |
878 |
879 |
880 | 635
881 | 590
882 | 150
883 | 25
884 |
885 |
886 |
887 | Save
888 |
889 |
890 |
891 |
892 | false
893 |
894 |
895 |
896 | 915
897 | 590
898 | 100
899 | 25
900 |
901 |
902 |
903 | Open DIR
904 |
905 |
906 |
907 |
908 | false
909 |
910 |
911 |
912 | 790
913 | 590
914 | 120
915 | 25
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 | 20
926 | 620
927 | 416
928 | 25
929 |
930 |
931 |
932 | QFrame::Panel
933 |
934 |
935 | QFrame::Sunken
936 |
937 |
938 | Select firmware file...
939 |
940 |
941 | Qt::PlainText
942 |
943 |
944 | false
945 |
946 |
947 | 0
948 |
949 |
950 |
951 |
952 |
953 | 445
954 | 620
955 | 75
956 | 25
957 |
958 |
959 |
960 | Browse
961 |
962 |
963 |
964 |
974 |
975 |
976 | false
977 |
978 |
979 | false
980 |
981 |
982 | Disconnected
983 |
984 |
985 |
986 |
987 |
988 |
989 | tableWidget
990 | cellClicked(int,int)
991 | editIPAddress
992 | update()
993 |
994 |
995 | 162
996 | 119
997 |
998 |
999 | 743
1000 | 119
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 | 5
1008 |
1009 |
1010 | 5
1011 |
1012 |
1013 | true
1014 |
1015 |
1016 | true
1017 |
1018 |
1019 | true
1020 |
1021 |
1022 |
1023 |
--------------------------------------------------------------------------------
/dms.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import struct
6 | import json
7 | from locale import getdefaultlocale
8 | from subprocess import check_output
9 | from socket import *
10 | from datetime import *
11 |
12 | import netifaces
13 | import logging
14 |
15 | from dvrip import DVRIPCam
16 |
17 | from PyQt5.QtWidgets import *
18 | from PyQt5.QtGui import *
19 | from PyQt5 import uic, QtCore, QtWidgets
20 | from PyQt5.QtCore import Qt, QSettings
21 |
22 | (Ui_MainWindow, QMainWindow) = uic.loadUiType('dms.ui')
23 | (Ui_Form, QtWidgets.QDialog) = uic.loadUiType('remotedevice.ui')
24 |
25 | cam = DVRIPCam('')
26 | udptimeout = 3
27 | tcptimeout = 10
28 |
29 | if os.path.exists('debug'):
30 | debug = True
31 | else:
32 | debug = False
33 |
34 | if debug:
35 | debugLevel = logging.DEBUG
36 | devices = ({'00:00:00:00:00:64': {'ChannelNum': 9, 'DeviceType': 4, 'GateWay': '0xFE01A8C0', 'HostIP': '0x0A01A8C0', 'HostName': 'NBD80N32RA-KL', 'HttpPort': 80, 'MAC': '00:00:00:00:00:64', 'MaxBps': 0, 'MonMode': 'TCP', 'NetConnectState': 0, 'OtherFunction': 'D=2023-03-21 13:21:32 V=78775aada187e84', 'SN': '0000000000000081', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'TransferPlan': 'Quality', 'UDPPort': 34568, 'UseHSDownLoad': False, 'Brand': 'xm'}, '00:00:00:00:00:17': {'ChannelNum': 1, 'DeviceType': 1, 'GateWay': '0x0101A8C0', 'HostIP': '0x0801A8C0', 'HostName': 'LocalHost', 'HttpPort': 80, 'MAC': '00:00:00:00:00:17', 'MaxBps': 0, 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:34 V=1482fd4408e15a7', 'SN': '0000000000000006', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'TransferPlan': 'Quality', 'UDPPort': 34568, 'UseHSDownLoad': False, 'Brand': 'xm'}, '00:00:00:00:00:1e': {'BuildDate': '2020-07-04 09:25:14', 'ChannelNum': 1, 'GateWay': '0x0101A8C0', 'HostIP': '0x0701A8C0', 'HostName': 'IVG-85HF20PYA-S', 'HttpPort': 80, 'MAC': '00:00:00:00:00:1e', 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:34 V=d0384e6d8a46c2f', 'SN': '0000000000000033', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'UDPPort': 34568, 'UseHSDownLoad': True, 'Version': 'V5.00.R02.000559A7.10010.040400.0020000', 'Brand': 'xm'}, '00:00:00:00:00:48': {'BuildDate': '2022- 2-23 16:34: 0', 'ChannelNum': 1, 'DeviceType': 0, 'GateWay': '0xFE01A8C0', 'HostIP': '0x0501A8C0', 'HostName': 'IVG-N4', 'HttpPort': 80, 'MAC': '00:00:00:00:00:48', 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:33 V=a721ad83d521bc7',
37 | 'SN': '000000000000002a', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'UDPPort': 34568, 'UseHSDownLoad': False, 'Version': 'V5.00.R02.000629G3.10010.140200.0020000', 'Brand': 'xm'}, '00:00:00:00:00:6b': {'BuildDate': '2020-07-04 09:25:14', 'ChannelNum': 1, 'GateWay': '0x0101A8C0', 'HostIP': '0x0401A8C0', 'HostName': 'IVG-85HF20PYA-S', 'HttpPort': 80, 'MAC': '00:00:00:00:00:6b', 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:33 V=088a5643e0387f2', 'SN': '0000000000000095', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'UDPPort': 34568, 'UseHSDownLoad': False, 'Version': 'V5.00.R02.000559A7.10010.040400.0020000', 'Brand': 'xm'}, '00:00:00:00:00:43': {'BuildDate': '2020-07-04 09:25:14', 'ChannelNum': 1, 'GateWay': '0x0201A8C0', 'HostIP': '0x0601A8C0', 'HostName': 'IVG-85HF20PYA-S', 'HttpPort': 80, 'MAC': '00:00:00:00:00:43', 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:34 V=6d1150f906f4948', 'SN': '0000000000000039', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'UDPPort': 34568, 'UseHSDownLoad': False, 'Version': 'V5.00.R02.000559A7.10010.040400.0020000', 'Brand': 'xm'}, '00:00:00:00:00:22': {'BuildDate': '2020- 9- 1 14:38:48', 'ChannelNum': 1, 'GateWay': '0x0101A8C0', 'HostIP': '0x6414A8C0', 'HostName': 'camera_', 'HttpPort': 80, 'MAC': '00:00:00:00:00:22', 'MonMode': 'TCP', 'NetConnectState': 1, 'OtherFunction': 'D=2023-03-21 13:21:34 V=bdf396972028edf', 'SN': '0000000000000061', 'SSLPort': 8443, 'Submask': '0x00FFFFFF', 'TCPMaxConn': 10, 'TCPPort': 34567, 'UDPPort': 34568, 'UseHSDownLoad': True, 'Version': 'V5.00.R02.000529B2.10010.040600.0020000', 'Brand': 'xm'}})
38 | RemoteDeviceV3 = [{"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "chConfig", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.1.10", "Interval": 10, "MacAddr": "", "MainRtspUrl": "", "PassWord": "", "Port": 34567, "Protocol": "TCP", "SerialNo": "", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": False, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": False, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 3, "ConfName": "LocalHost", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.20.5", "Interval": 10, "MacAddr": "00:00:00:00:00:49", "MainRtspUrl": "", "PassWord": "assword", "Port": 34567, "Protocol": "TCP", "SerialNo": "0000000000000054", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": False, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "SmartNet", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.1.11", "Interval": 10, "MacAddr": "00:00:00:00:00:e4", "MainRtspUrl": "", "PassWord": "", "Port": 34567, "Protocol": "TCP", "SerialNo": "000000000000009b", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": False, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "LocalHost", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.20.253", "Interval": 10, "MacAddr": "00:00:00:00:00:f6", "MainRtspUrl": "", "PassWord": "assword", "Port": 34567, "Protocol": "TCP", "SerialNo": "00000000000000d8", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": True, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "chConfig", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.1.9", "Interval": 10, "MacAddr": "", "MainRtspUrl": "", "PassWord": "", "Port": 34567, "Protocol": "TCP", "SerialNo": "", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": True, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "IVG-85HF20PYA-S", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.250.249", "Interval": 10,
39 | "MacAddr": "00:00:00:00:00:63", "MainRtspUrl": "", "PassWord": "2assword", "Port": 34567, "Protocol": "TCP", "SerialNo": "00000000000000b2", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": True, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "LocalHost", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.54.214", "Interval": 10, "MacAddr": "00:00:00:00:00:af", "MainRtspUrl": "", "PassWord": "", "Port": 34567, "Protocol": "TCP", "SerialNo": "00000000000000c9", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": True, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": [{"Channel": 0, "ConfName": "Hikvision", "DevType": "IPC", "Enable": True, "IPAddress": "192.168.1.64", "Interval": 10, "MacAddr": "00:00:00:00:00:2b", "MainRtspUrl": "", "PassWord": "a1234567", "Port": 80, "Protocol": "ONVIF", "SerialNo": "", "StreamType": "MAIN", "SubRtspUrl": "", "TransModel": 0, "UserName": "admin"}], "EnCheckTime": True, "Enable": True, "SingleConnId": "0x00000001", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}, {"ConnType": "SINGLE", "Decoder": 'null', "EnCheckTime": True, "Enable": False, "SingleConnId": "0x00000000", "SynchResolution": True, "TourIntv": 10}]
40 | ChannelTitle = ["CAM01", "Test2", "D03", "5MP 123456789 0",
41 | "D05", "CAM04", "D07", "D08", "D09", "D10", "D11", "D12", "D13", "D14", "D15", "D16"]
42 | DecodeParam = [{"deleyTimeMs": 150}, {"deleyTimeMs": 333}, {"deleyTimeMs": 2000}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {
43 | "deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}, {"deleyTimeMs": 333}]
44 | DigTimeSyn = [{"TimeSyn": "OFF"}, {"TimeSyn": "OFF"}, {"TimeSyn": "OFF"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {
45 | "TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}, {"TimeSyn": "T&Z"}]
46 | DecodeDeleyTime = ["0x00000096", "0x000000FA", "0x0000014D",
47 | "0x0000029B", "0x000003E8", "0x000007D0", "0x00000BB8"]
48 | NetLocalSearch = [{"ChannelNum": 16, "DeviceType": 305201157, "GateWay": "0xFE01A8C0", "HostIP": "0x0401A8C0", "HostName": "NBD80S16S-KL", "HttpPort": 80, "MAC": "00:00:00:00:00:b6", "Manufacturer": 4, "MaxBps": 0, "MonMode": "TCP", "NetConnectState": 0, "OtherFunction": "", "SN": "00000000000000cfcdp6", "SSLPort": 8443, "Submask": "0x00FFFFFF", "TCPMaxConn": 10, "TCPPort": 34567, "TransferPlan": "Quality", "UDPPort": 34568, "UseHSDownLoad": False, "pAddr": "", "pGateway": "", "pLocalLinkAddr": ""}, {"ChannelNum": 4, "DeviceType": 305201156, "GateWay": "0x0201A8C0", "HostIP": "0x0801A8C0", "HostName": "LocalHost", "HttpPort": 80, "MAC": "00:00:00:00:00:71", "Manufacturer": 4, "MaxBps": 0, "MonMode": "TCP", "NetConnectState": 1,
49 | "OtherFunction": "", "SN": "0000000000000041", "SSLPort": 8443, "Submask": "0x00FFFFFF", "TCPMaxConn": 10, "TCPPort": 34567, "TransferPlan": "Quality", "UDPPort": 34568, "UseHSDownLoad": False, "pAddr": "", "pGateway": "", "pLocalLinkAddr": ""}, {"ChannelNum": 1, "DeviceType": 0, "GateWay": "0xFE01A8C0", "HostIP": "0x0601A8C0", "HostName": "LocalHost", "HttpPort": 80, "MAC": "00:00:00:00:00:ce", "Manufacturer": 4, "MaxBps": 0, "MonMode": "TCP", "NetConnectState": 1, "OtherFunction": "", "SN": "0000000000000083", "SSLPort": 8443, "Submask": "0x00FFFFFF", "TCPMaxConn": 10, "TCPPort": 34567, "TransferPlan": "Transmission", "UDPPort": 34568, "UseHSDownLoad": False, "pAddr": "", "pGateway": "", "pLocalLinkAddr": ""}, {"ChannelNum": 1, "DeviceType": 7, "GateWay": "0xFE01A8C0", "HostIP": "0x0701A8C0", "HostName": "LocalHost", "HttpPort": 80, "MAC": "00:00:00:00:00:cf", "Manufacturer": 4, "MaxBps": 0, "MonMode": "TCP", "NetConnectState": 1, "OtherFunction": "", "SN": "0000000000000084", "SSLPort": 8443, "Submask": "0x00FFFFFF", "TCPMaxConn": 10, "TCPPort": 34567, "TransferPlan": "Transmission", "UDPPort": 34568, "UseHSDownLoad": False, "pAddr": "", "pGateway": "", "pLocalLinkAddr": ""}]
50 | else:
51 | debugLevel = logging.INFO
52 | devices = {}
53 |
54 |
55 | def log(*args):
56 | # logging.debug(*args)
57 | print(*args)
58 |
59 |
60 | logging.basicConfig(format='%(asctime)s> %(message)s',
61 | level=debugLevel, datefmt='[%H:%M:%S]')
62 |
63 |
64 | class RemoteDevices(QtWidgets.QDialog, Ui_Form):
65 | def __init__(self, parent=None):
66 | QtWidgets.QDialog.__init__(self, parent=parent)
67 | self.setupUi(self)
68 |
69 | def keyPressEvent(self, event):
70 | if event.key() == QtCore.Qt.Key_Escape:
71 | self.hide()
72 |
73 |
74 | class MainWindow (QMainWindow):
75 | def __init__(self, parent=None):
76 | QMainWindow.__init__(self, parent)
77 | self.ui = Ui_MainWindow()
78 | self.ui.setupUi(self)
79 |
80 | def __del__(self):
81 | self.ui = None
82 |
83 | def filedialog(self):
84 | options = QFileDialog.Options()
85 | fileName, _ = QFileDialog.getOpenFileName(
86 | self, "Select upgrade file", settings.value("fwdir", '.'), "Firmware files (*.bin)", options=options)
87 | if fileName:
88 | self.ui.labFilename.setText(fileName)
89 | settings.setValue("fwdir", os.path.dirname(fileName))
90 |
91 | def getCheckedDevices(self, column):
92 | checked_list = []
93 | for i in range(self.ui.tableWidget.rowCount()):
94 | if self.ui.tableWidget.cellWidget(i, 0).isChecked():
95 | selected_dev = self.ui.tableWidget.item(i, column).text()
96 | checked_list.append([selected_dev])
97 | else:
98 | pass
99 | return checked_list
100 |
101 | def btnAutoIP(self):
102 | for dev in w.getCheckedDevices(3):
103 | log(dev[0])
104 | # tcpSetAddresses(['config', dev[0], w.ui.editIPAddress.text(), w.ui.editSubnetAddress.text(), w.ui.editGatewayAddress.text(), ''])
105 |
106 | def btnChangePassword(self):
107 | newPassword = self.ui.editNewPassword.text()
108 | if newPassword:
109 | log(self.getCheckedDevices(1), newPassword)
110 |
111 | def onRowClick(self):
112 | selected_dev = w.ui.tableWidget.item(
113 | self.ui.tableWidget.currentRow(), 3).text()
114 | self.ui.editIPAddress.setText(ip2str(devices[selected_dev]["HostIP"]))
115 | self.ui.editSubnetAddress.setText(
116 | ip2str(devices[selected_dev]["Submask"]))
117 | self.ui.editGatewayAddress.setText(
118 | ip2str(devices[selected_dev]["GateWay"]))
119 | # w.ui.editDNS1Address.setText(ip2str(devices[selected_dev]["DNS"]))
120 | # for item in devices:
121 | # print(item)
122 | # print(devices[selected_dev])
123 | # print(devices[1])
124 | # self.ui.statusbar.showMessage(selected_dev)
125 |
126 | def keyPressEvent(self, event):
127 | if event.key() == QtCore.Qt.Key_Escape:
128 | app.quit()
129 |
130 |
131 | def onBtnSearch():
132 | global devices
133 | QApplication.setOverrideCursor(Qt.WaitCursor)
134 | if not debug:
135 | devices = {}
136 | try:
137 | devices = udpSearch(devices)
138 | except Exception as error:
139 | print(" ".join([str(x) for x in list(error.args)]))
140 | QApplication.restoreOverrideCursor()
141 | count = 0
142 | w.ui.tableWidget.setRowCount(len(devices))
143 | for dev in devices:
144 | w.ui.tableWidget.setCellWidget(count, 0, QCheckBox())
145 | w.ui.tableWidget.setItem(count, 1, QTableWidgetItem(
146 | ip2str(devices[dev]["HostIP"])))
147 | w.ui.tableWidget.setItem(
148 | count, 2, QTableWidgetItem(str(devices[dev]["TCPPort"])))
149 | w.ui.tableWidget.setItem(
150 | count, 3, QTableWidgetItem(devices[dev]["MAC"]))
151 | w.ui.tableWidget.setItem(
152 | count, 4, QTableWidgetItem(devices[dev]["SN"]))
153 | w.ui.tableWidget.setItem(count, 5, QTableWidgetItem(
154 | devices[dev].get("Version", "")[0:18]))
155 | w.ui.tableWidget.setItem(count, 6, QTableWidgetItem(
156 | devices[dev].get("BuildDate", "")[0:10]))
157 | w.ui.tableWidget.setItem(
158 | count, 7, QTableWidgetItem(devices[dev]["HostName"]))
159 | count += 1
160 |
161 |
162 | def ip2str(s):
163 | return inet_ntoa(struct.pack("I", int(s, 16)))
164 |
165 |
166 | def str2ip(s):
167 | return "0x%08X" % struct.unpack("I", inet_aton(s))
168 |
169 |
170 | def udpSearch(devices):
171 | sender = socket(AF_INET, SOCK_DGRAM)
172 | sender.bind((w.ui.comboIPAddresses.currentText(), 0))
173 | sender.settimeout(1)
174 | sender.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
175 | sender.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
176 |
177 | listener = socket(AF_INET, SOCK_DGRAM)
178 | listener.bind(('', 34569))
179 | listener.settimeout(udptimeout)
180 | listener.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
181 | listener.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
182 | for i in range(2):
183 | sender.sendto(
184 | struct.pack("BBHIIHHI", 255, 0, 0, 0, 0, 0,
185 | 1530, 0), ("255.255.255.255", 34569)
186 | )
187 | while True:
188 | data = listener.recvfrom(1024)
189 | head, ver, typ, session, packet, info, msg, leng = struct.unpack(
190 | "BBHIIHHI", data[0][:20]
191 | )
192 | if (msg == 1531) and leng > 0:
193 | answer = json.loads(
194 | data[0][20: 20 + leng].replace(b"\x00", b""))
195 | if answer["NetWork.NetCommon"]["MAC"] not in devices.keys():
196 | devices[answer["NetWork.NetCommon"]["MAC"]] = answer[
197 | "NetWork.NetCommon"
198 | ]
199 | devices[answer["NetWork.NetCommon"]["MAC"]][u"Brand"] = u"xm"
200 | return devices
201 |
202 |
203 | def cbProgress(s):
204 | w.ui.statusbar.showMessage(s)
205 |
206 |
207 | def upgradeFirmware(ip, username, password, filename):
208 | QApplication.setOverrideCursor(Qt.WaitCursor)
209 | if cam.login():
210 | log("Auth success")
211 | cam.upgrade(filename, 0x4000, cbProgress)
212 | else:
213 | log("Auth failed")
214 | QApplication.restoreOverrideCursor()
215 |
216 |
217 | def udpSetAddresses(data):
218 | config = {}
219 | for k in [u"HostName", u"HttpPort", u"MAC", u"MaxBps", u"MonMode", u"SSLPort", u"TCPMaxConn", u"TCPPort", u"TransferPlan", u"UDPPort", "UseHSDownLoad"]:
220 | if k in devices[data[1]]:
221 | config[k] = devices[data[1]][k]
222 | config[u"DvrMac"] = devices[data[1]][u"MAC"]
223 | config[u"EncryptType"] = 1
224 | config[u"GateWay"] = str2ip(data[4])
225 | config[u"HostIP"] = str2ip(data[2])
226 | config[u"Submask"] = str2ip(data[3])
227 | config[u"Username"] = w.ui.editUsername.text()
228 | config[u"Password"] = DVRIPCam.sofia_hash(
229 | '', w.ui.editCurrentPassword.text())
230 | devices[data[1]][u"GateWay"] = config[u"GateWay"]
231 | devices[data[1]][u"HostIP"] = config[u"HostIP"]
232 | devices[data[1]][u"Submask"] = config[u"Submask"]
233 | config = json.dumps(
234 | config, ensure_ascii=False, sort_keys=True, separators=(", ", " : ")
235 | ).encode("utf8")
236 | if not debug:
237 | server = socket(AF_INET, SOCK_DGRAM)
238 | server.bind((w.ui.comboIPAddresses.currentText(), 34569))
239 | server.settimeout(udptimeout)
240 | server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
241 | server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
242 | clen = len(config)
243 |
244 | server.sendto(
245 | struct.pack(
246 | "BBHIIHHI%ds2s" % clen,
247 | 255,
248 | 0,
249 | 254,
250 | 0,
251 | 0,
252 | 0,
253 | 1532,
254 | clen + 2,
255 | config,
256 | b"\x0a\x00",
257 | ),
258 | ("255.255.255.255", 34569),
259 | )
260 | answer = {"Ret": 203}
261 | e = 0
262 | while True:
263 | try:
264 | data = server.recvfrom(1024)
265 | head, ver, typ, session, packet, info, msg, leng = struct.unpack(
266 | "BBHIIHHI", data[0][:20]
267 | )
268 | if (msg == 1533) and leng > 0:
269 | answer = json.loads(
270 | data[0][20: 20 + leng].replace(b"\x00", b""))
271 | break
272 | except:
273 | e += 1
274 | if e > 3:
275 | break
276 | server.close()
277 | return answer
278 |
279 |
280 | def btnSave():
281 | if w.ui.tableWidget.selectedItems():
282 | QApplication.setOverrideCursor(Qt.WaitCursor)
283 | selected_dev = w.ui.tableWidget.item(
284 | w.ui.tableWidget.currentRow(), 3).text()
285 | udpSetAddresses(['config', selected_dev, w.ui.editIPAddress.text(
286 | ), w.ui.editSubnetAddress.text(), w.ui.editGatewayAddress.text(), ''])
287 | QApplication.restoreOverrideCursor()
288 |
289 |
290 | def btnUpgrade():
291 | if w.ui.tableWidget.selectedItems() and w.ui.labFilename.text():
292 | QApplication.setOverrideCursor(Qt.WaitCursor)
293 | selected_dev = w.ui.tableWidget.item(
294 | w.ui.tableWidget.currentRow(), 1).text()
295 | upgradeFirmware(w.ui.editIPAddress.text(), w.ui.editUsername.text(
296 | ), w.ui.editCurrentPassword.text(), w.ui.labFilename.text())
297 | QApplication.restoreOverrideCursor()
298 |
299 |
300 | def netipLogin():
301 | global cam
302 | if w.ui.tableWidget.selectedItems():
303 | selected_dev = w.ui.tableWidget.item(
304 | w.ui.tableWidget.currentRow(), 1).text()
305 | ip = w.ui.editIPAddress.text()
306 | username = w.ui.editUsername.text()
307 | password = w.ui.editCurrentPassword.text()
308 |
309 | if not cam.socket:
310 | QApplication.setOverrideCursor(Qt.WaitCursor)
311 | cam = DVRIPCam(ip, username=username, password=password)
312 | if cam.login():
313 | w.ui.status2.setText(w.tr(f"Connected to {ip}"))
314 | else:
315 | w.ui.status2.setText(w.tr("Login failed"))
316 | QApplication.restoreOverrideCursor()
317 |
318 | return cam
319 | else:
320 | w.ui.status2.setText(w.tr(f"Disconnected"))
321 | cam.close()
322 |
323 |
324 | def netipSendCommand(command, *args):
325 | if cam.login():
326 | getattr(cam, command)(*args)
327 | w.ui.statusbar.showMessage(w.tr(f"{command} OK"))
328 | else:
329 | w.ui.statusbar.showMessage(w.tr("Command failed"))
330 |
331 |
332 | def getDigitalChannels():
333 | global RemoteDeviceV3
334 | QApplication.setOverrideCursor(Qt.WaitCursor)
335 | if not debug:
336 | RemoteDeviceV3 = {}
337 | try:
338 | if cam.login():
339 | RemoteDeviceV3 = cam.get_info("NetWork.RemoteDeviceV3")
340 | r.show()
341 | except Exception as error:
342 | print(" ".join([str(x) for x in list(error.args)]))
343 | else:
344 | r.show()
345 | QApplication.restoreOverrideCursor()
346 | r.tableChannels.setRowCount(len(RemoteDeviceV3))
347 | count = 0
348 | for channel in RemoteDeviceV3:
349 | chkBoxEnable = QTableWidgetItem()
350 | chkBoxEnable.setFlags(
351 | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
352 | if RemoteDeviceV3[count]['Enable']:
353 | chkBoxEnable.setCheckState(QtCore.Qt.Checked)
354 | else:
355 | chkBoxEnable.setCheckState(QtCore.Qt.Unchecked)
356 | r.tableChannels.setItem(count, 0, chkBoxEnable)
357 |
358 | r.tableChannels.setItem(
359 | count, 1, QTableWidgetItem(str(ChannelTitle[count])))
360 |
361 | comboSyncRes = QComboBox()
362 | comboSyncRes.setFrame(False)
363 | comboSyncRes.addItems(['False', 'True'])
364 | r.tableChannels.setCellWidget(count, 4, comboSyncRes)
365 |
366 | comboTimeSyn = QComboBox()
367 | comboTimeSyn.setFrame(False)
368 | comboTimeSyn.addItems(['OFF', 'T&Z', 'Local', 'UTC'])
369 | r.tableChannels.setCellWidget(count, 5, comboTimeSyn)
370 |
371 | comboDelayDecode = QComboBox()
372 | comboDelayDecode.setFrame(False)
373 | comboDelayDecode.addItems([str(int(x, 16)) for x in DecodeDeleyTime])
374 | r.tableChannels.setIndexWidget(
375 | r.tableChannels.model().index(count, 6), comboDelayDecode)
376 |
377 | comboProtocol = QComboBox()
378 | comboProtocol.setFrame(False)
379 | comboProtocol.addItems(['TCP', 'ONVIF', 'RTSP'])
380 | r.tableChannels.setCellWidget(count, 8, comboProtocol)
381 |
382 | if RemoteDeviceV3[count]['Decoder'] != 'null':
383 | r.tableChannels.setItem(count, 2, QTableWidgetItem(
384 | str(RemoteDeviceV3[count]['Decoder'][0]['IPAddress'])))
385 | r.tableChannels.setItem(count, 3, QTableWidgetItem(
386 | str(RemoteDeviceV3[count]['Decoder'][0]['Port'])))
387 | comboSyncRes.setCurrentText(
388 | str(not RemoteDeviceV3[count]['SynchResolution']))
389 | comboTimeSyn.setCurrentText(str(str(DigTimeSyn[count]['TimeSyn'])))
390 | comboDelayDecode.setCurrentText(
391 | str(DecodeParam[count]['deleyTimeMs']))
392 | r.tableChannels.setItem(count, 7, QTableWidgetItem(
393 | str(RemoteDeviceV3[count]['Decoder'][0]['Channel'])))
394 | comboProtocol.setCurrentText(
395 | str(RemoteDeviceV3[count]['Decoder'][0]['Protocol']))
396 | r.tableChannels.setItem(count, 9, QTableWidgetItem(
397 | RemoteDeviceV3[count]['Decoder'][0]['UserName']))
398 | r.tableChannels.setItem(count, 10, QTableWidgetItem(
399 | RemoteDeviceV3[count]['Decoder'][0]['PassWord']))
400 | count += 1
401 |
402 |
403 | def btnDigitalChannelsSave():
404 | trow = []
405 | for row in range(16):
406 | for i in range(2, 7):
407 | try:
408 | trow.append(r.tableChannels.item(
409 | r.tableChannels.verticalHeader().logicalIndex(row), i).text())
410 | except:
411 | print(" ".join([str(x) for x in list(error.args)]))
412 | print(trow)
413 |
414 |
415 | def btnDigitalSearch():
416 | global NetLocalSearch
417 | QApplication.setOverrideCursor(Qt.WaitCursor)
418 | if not debug:
419 | NetLocalSearch = {}
420 | try:
421 | if cam.login():
422 | NetLocalSearch = cam.get_info("NetLocalSearch")
423 | except Exception as error:
424 | print(" ".join([str(x) for x in list(error.args)]))
425 | QApplication.restoreOverrideCursor()
426 | count = 0
427 | r.tableSearch.setRowCount(len(NetLocalSearch))
428 | for dev in NetLocalSearch:
429 | r.tableSearch.setItem(
430 | count, 0, QTableWidgetItem(ip2str(dev["HostIP"])))
431 | r.tableSearch.setItem(
432 | count, 1, QTableWidgetItem(str(dev["TCPPort"])))
433 | r.tableSearch.setItem(
434 | count, 2, QTableWidgetItem(dev["MAC"]))
435 | r.tableSearch.setItem(
436 | count, 3, QTableWidgetItem(dev["SN"]))
437 | devtype = {305201157: 'NVR', 305201156: 'DVR', 7: 'IPCWIFI', 0: 'IPC'}
438 | r.tableSearch.setItem(count, 4, QTableWidgetItem(dev["HostName"]))
439 | r.tableSearch.setItem(
440 | count, 5, QTableWidgetItem(str(dev["ChannelNum"])))
441 | r.tableSearch.setItem(
442 | count, 6, QTableWidgetItem(devtype[dev["DeviceType"]]))
443 | count += 1
444 |
445 |
446 | def onComboSelectInterface():
447 | iface = str(w.ui.comboInterfaces.currentText())
448 | w.ui.comboIPAddresses.clear()
449 | for addr_info in netifaces.ifaddresses(iface)[netifaces.AF_INET]:
450 | w.ui.comboIPAddresses.addItem(
451 | str(addr_info['addr']))
452 | w.ui.comboIPAddresses.setCurrentText(
453 | str(netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr']))
454 |
455 |
456 | if __name__ == '__main__':
457 | app = QApplication(sys.argv)
458 | app.setOrganizationName("OpenIPC")
459 | app.setOrganizationDomain("openipc.org")
460 | app.setApplicationName("DMS")
461 | settings = QSettings()
462 | # locale = getdefaultlocale()
463 | locale = 'ru'
464 |
465 | translator = QtCore.QTranslator(app)
466 | translator.load('res/%s.qm' % locale[0])
467 | app.installTranslator(translator)
468 |
469 | w = MainWindow()
470 | w.show()
471 | r = RemoteDevices()
472 |
473 | r.tableChannels.setColumnWidth(0, 5)
474 | r.tableChannels.setColumnWidth(1, 150)
475 | r.tableChannels.setColumnWidth(2, 110)
476 | r.tableChannels.setColumnWidth(3, 50)
477 | r.tableChannels.setColumnWidth(4, 75)
478 | r.tableChannels.setColumnWidth(5, 75)
479 | r.tableChannels.setColumnWidth(6, 75)
480 | r.tableChannels.setColumnWidth(7, 50)
481 | r.tableChannels.setColumnWidth(8, 65)
482 | r.tableChannels.setColumnWidth(9, 75)
483 | r.tableChannels.setColumnWidth(10, 85)
484 | # r.tableChannels.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
485 | r.tableChannels.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
486 | r.tableChannels.verticalHeader().setSectionsMovable(True)
487 | r.tableChannels.verticalHeader().setAcceptDrops(True)
488 | r.btnDigitalChannelsSave.clicked.connect(btnDigitalChannelsSave)
489 |
490 | r.tableSearch.setColumnWidth(0, 110)
491 | r.tableSearch.setColumnWidth(1, 50)
492 | r.tableSearch.setColumnWidth(2, 120)
493 | r.tableSearch.setColumnWidth(3, 155)
494 | r.tableSearch.setColumnWidth(4, 200)
495 | r.tableSearch.setColumnWidth(5, 50)
496 | r.tableSearch.verticalHeader().setSectionsMovable(True)
497 | r.btnDigitalSearch.clicked.connect(btnDigitalSearch)
498 |
499 | w.ui.btnAutoIP.clicked.connect(w.btnAutoIP)
500 | w.ui.searchDevices.clicked.connect(onBtnSearch)
501 | w.ui.btnBrowse.clicked.connect(w.filedialog)
502 | w.ui.btnSave.clicked.connect(btnSave)
503 | w.ui.btnUpgrade.clicked.connect(btnUpgrade)
504 | w.ui.btnReboot.clicked.connect(lambda: netipSendCommand("reboot"))
505 | w.ui.btnDigitalChannels.clicked.connect(getDigitalChannels)
506 | w.ui.btnChangePassword.clicked.connect(w.btnChangePassword)
507 | w.ui.tableWidget.cellClicked.connect(w.onRowClick)
508 | w.ui.tableWidget.cellDoubleClicked.connect(netipLogin)
509 | w.ui.comboInterfaces.currentTextChanged.connect(onComboSelectInterface)
510 |
511 | w.ui.tableWidget.horizontalHeader().resizeSection(0, 1)
512 | w.ui.tableWidget.horizontalHeader().setSectionResizeMode(
513 | QHeaderView.ResizeToContents)
514 |
515 | w.ui.statusbar.setFixedHeight(25)
516 | w.ui.statusbar.showMessage(w.tr("Idle"))
517 | w.ui.status2 = QLabel("Disconnected")
518 | w.ui.statusbar.addPermanentWidget(w.ui.status2)
519 |
520 | # need to find replacement for netifaces, no binary builds for python 3.10 on windows
521 | hostinterfaces = netifaces.interfaces()
522 | hostdefaultgw = netifaces.gateways()['default'][netifaces.AF_INET][1]
523 | badinterfaces = ['lo', 'docker', 'veth', 'vbox']
524 | for iface in hostinterfaces:
525 | addrs = netifaces.ifaddresses(iface)
526 | if netifaces.AF_INET not in addrs:
527 | badinterfaces.append(iface)
528 | w.ui.comboInterfaces.addItems(
529 | [x for x in hostinterfaces if not any(x.startswith(s) for s in badinterfaces)])
530 | if hostdefaultgw:
531 | w.ui.comboInterfaces.setCurrentText(hostdefaultgw)
532 |
533 | sys.exit(app.exec_())
534 |
--------------------------------------------------------------------------------