├── .eslintrc.json
├── .gitignore
├── .idea
├── encodings.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jsLibraryMappings.xml
├── misc.xml
├── modules.xml
├── preferred-vcs.xml
├── telepresenceCommands.iml
├── vcs.xml
├── watcherTasks.xml
└── workspace.xml
├── LICENSE.md
├── README.md
├── endpointLogs
├── Thu, 29 Mar 2018 16:01:31 GMT.x-gzip
└── readme.txt
├── endpoints
└── endpoints.csv
├── gulpfile.js
├── img
├── brand
│ └── expedia.jpg
├── oldImages
│ ├── expedia.jpg
│ └── kaiser-permanente272.jpg
└── wallpaper
│ └── Kaiser-Permanente-Exterior.jpg
├── package.json
├── server.js
├── svrConfig
├── comFunct.js
├── httpServer.js
└── logger.js
├── tools
├── buildXml.js
├── collectLogs.js
├── endpoint.js
├── excel.js
├── fileWatcher.js
├── image64.js
├── ipaddress.js
└── tpXapi.js
└── xmlFiles
├── backupBundle
└── backup-bundle.zip
├── macros
└── proximityMacro.js
├── readme.txt
└── roomControls
└── proximityButton.xml
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": [
4 | "eslint:recommended",
5 | "plugin:import/errors",
6 | "plugin:import/warnings"
7 | ],
8 | "parserOptions": {
9 | "ecmaVersion": 7,
10 | "sourceType": "module"
11 | },
12 | "env": {
13 | "browser": true,
14 | "node": true,
15 | "mocha": true
16 | },
17 | "rules": {
18 | "no-console": 0
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cloud 9 files
2 | .c9/
3 | # Space date
4 | space.json
5 | cart.json
6 | #client websocket file
7 | device.json
8 | #access log
9 | access.log
10 | /endpointLogs
11 |
12 | # Logs
13 | logs
14 | *.log
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 |
19 | # Runtime data
20 | pids
21 | *.pid
22 | *.seed
23 | *.pid.lock
24 |
25 | # Directory for instrumented libs generated by jscoverage/JSCover
26 | lib-cov
27 |
28 | # Coverage directory used by tools like istanbul
29 | coverage
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Typescript v1 declaration files
51 | typings/
52 |
53 | # Optional npm cache directory
54 | .npm
55 |
56 | # Optional eslint cache
57 | .eslintcache
58 |
59 | # Optional REPL history
60 | .node_repl_history
61 |
62 | # Output of 'npm pack'
63 | *.tgz
64 |
65 | # Yarn Integrity file
66 | .yarn-integrity
67 |
68 | # dotenv environment variables file
69 | .env
70 | .idea/
71 |
72 | # User-specific stuff:
73 | .idea/**/workspace.xml
74 | .idea/**/tasks.xml
75 | .idea/dictionaries
76 |
77 | # Sensitive or high-churn files:
78 | .idea/**/dataSources/
79 | .idea/**/dataSources.ids
80 | .idea/**/dataSources.local.xml
81 | .idea/**/sqlDataSources.xml
82 | .idea/**/dynamic.xml
83 | .idea/**/uiDesigner.xml
84 |
85 | # Gradle:
86 | .idea/**/gradle.xml
87 | .idea/**/libraries
88 |
89 | # CMake
90 | cmake-build-debug/
91 | cmake-build-release/
92 |
93 | # Mongo Explorer plugin:
94 | .idea/**/mongoSettings.xml
95 |
96 | ## File-based project format:
97 | *.iws
98 |
99 | ## Plugin-specific files:
100 |
101 | # IntelliJ
102 | out/
103 |
104 | # mpeltonen/sbt-idea plugin
105 | .idea_modules/
106 |
107 | # JIRA plugin
108 | atlassian-ide-plugin.xml
109 |
110 | # Cursive Clojure plugin
111 | .idea/replstate.xml
112 |
113 | # Crashlytics plugin (for Android Studio and IntelliJ)
114 | com_crashlytics_export_strings.xml
115 | crashlytics.properties
116 | crashlytics-build.properties
117 | fabric.properties
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | true
8 |
9 | false
10 | true
11 |
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/preferred-vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ApexVCS
5 |
6 |
--------------------------------------------------------------------------------
/.idea/telepresenceCommands.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/watcherTasks.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | conn
144 | connect
145 | cart
146 | _
147 | console
148 |
149 |
150 |
151 |
152 |
153 |
154 |
198 |
199 |
200 |
201 |
202 | true
203 | DEFINITION_ORDER
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 | project
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 | project
484 |
485 |
486 | true
487 |
488 |
489 |
490 | DIRECTORY
491 |
492 | false
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 | 1515446082004
503 |
504 |
505 | 1515446082004
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 | 1520978863692
519 |
520 |
521 |
522 | 1520978863692
523 |
524 |
525 | 1520979009241
526 |
527 |
528 |
529 | 1520979009241
530 |
531 |
532 | 1520979214613
533 |
534 |
535 |
536 | 1520979214613
537 |
538 |
539 | 1520979357067
540 |
541 |
542 |
543 | 1520979357067
544 |
545 |
546 | 1520979618282
547 |
548 |
549 |
550 | 1520979618282
551 |
552 |
553 | 1520980628484
554 |
555 |
556 |
557 | 1520980628484
558 |
559 |
560 | 1521053380436
561 |
562 |
563 |
564 | 1521053380436
565 |
566 |
567 | 1521060143254
568 |
569 |
570 |
571 | 1521060143254
572 |
573 |
574 | 1522096094040
575 |
576 |
577 |
578 | 1522096094040
579 |
580 |
581 | 1522165475672
582 |
583 |
584 |
585 | 1522165475673
586 |
587 |
588 | 1522257603638
589 |
590 |
591 |
592 | 1522257603638
593 |
594 |
595 | 1522260734853
596 |
597 |
598 |
599 | 1522260734854
600 |
601 |
602 | 1522261082359
603 |
604 |
605 |
606 | 1522261082359
607 |
608 |
609 | 1522699920928
610 |
611 |
612 |
613 | 1522699920928
614 |
615 |
616 | 1522700698832
617 |
618 |
619 |
620 | 1522700698833
621 |
622 |
623 | 1522702769195
624 |
625 |
626 |
627 | 1522702769195
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 |
995 |
996 |
997 |
998 |
999 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1028 |
1029 |
1030 |
1031 |
1032 |
1033 |
1034 |
1035 |
1036 |
1037 |
1038 |
1039 |
1040 |
1041 |
1042 |
1043 |
1044 |
1045 |
1046 |
1047 |
1048 |
1049 |
1050 |
1051 |
1052 |
1053 |
1054 |
1055 |
1056 |
1057 |
1058 |
1059 |
1060 |
1061 |
1062 |
1063 |
1064 |
1065 |
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 |
1076 |
1077 |
1078 |
1079 |
1080 |
1081 |
1082 |
1083 |
1084 |
1085 |
1086 |
1087 |
1088 |
1089 |
1090 |
1091 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Telepresence Deploy XML APP
2 |
3 | Simple app to deploy packages to Cisco Telepresence apps.
4 | Branding for CE9.2.1+ and backup bundles for CE9.3+ devices is supported. Backup bundles is a new features for CE9.3+ firmware.
5 |
6 | Currently capable of deploying:
7 | * Custom Branding with little fuss. Checks the endpoint if its branding capable via firmware version. Takes care of reading CSV files for endpoints and also base64 encoding of image files.
8 | * Using the branding option the script will check your endpoint version and deploy branding to endpoints capable or wallpaper for non-branding capable devices. SX10 check is supported. SX10 has no branding option even if Firmware is CE9.3.
9 | * Deploy wallpaper images (also disables branding)to all your endpoints instead of using the branding option.
10 | * Backup bundle to multiple endpoints. Will create the backup bundle checksum for deployment and acts as http server for package delivery.
11 |
12 | ## Getting Started
13 |
14 | The following applications and hardware are required:
15 |
16 |
17 | * Cisco Video endpoint
18 | * Nodejs
19 | * CSV file with IP addresses for endpoints placed in the Endpoint directory
20 | * Image files to be deployed placed in branding and wallpaper directories
21 | * Branding image 272x272 preferred
22 | * Background Image 1920x1080 preferred
23 | * Backup bundle created using CE9.3 device
24 | ### Prerequisites
25 |
26 | Configuration required:
27 |
28 | * Video endpoint
29 |
30 |
31 | ### Installing
32 |
33 | #### Via Git
34 | ```bash
35 | mkdir myproj
36 | cd myproj
37 | git clone https://github.com/voipnorm/CiscoTPCustomXML.git
38 | npm install
39 |
40 | ```
41 |
42 | Set the following environment variables in a .env file...
43 |
44 | ```
45 | PORT=
46 | TPADMIN=
47 | TPADMINPWD=
48 |
49 | ```
50 | ## Running Script
51 | To run the script use one of the following commands:
52 | ```
53 | node server.js branding
54 | ```
55 | or
56 | ```
57 | node server.js bundle
58 | ```
59 | To use the bundle command ensure you have created a backup bundle from your CE device and placed the zip file into:
60 | ```
61 | ./xmlFiles/backupBundle
62 | ```
63 | To deploy wallpaper:
64 | ```
65 | node server.js wallpaper
66 | ```
67 | Ensure wallpaper image is available in ./img/wallpaper directory.
68 | ## Built With
69 |
70 | * Nodejs
71 |
72 | ## License
73 |
74 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
75 |
76 | ## Acknowledgments
77 |
78 | * Me
79 |
80 |
--------------------------------------------------------------------------------
/endpointLogs/Thu, 29 Mar 2018 16:01:31 GMT.x-gzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/endpointLogs/Thu, 29 Mar 2018 16:01:31 GMT.x-gzip
--------------------------------------------------------------------------------
/endpointLogs/readme.txt:
--------------------------------------------------------------------------------
1 | downloaded endpoint logs will apear in this directory.
2 |
3 | Use "node server.js logs "
--------------------------------------------------------------------------------
/endpoints/endpoints.csv:
--------------------------------------------------------------------------------
1 | 10.27.42.116
2 | 10.27.42.117
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var nodemon = require('gulp-nodemon');
3 | var gulpMocha = require('gulp-mocha');
4 | var eslint = require('gulp-eslint');
5 | var env = require('gulp-env');
6 |
7 | gulp.task('default',['lint','test'], function(){
8 | nodemon({
9 | exec: 'node',
10 | script: 'server.js',
11 | ext: 'js',
12 | env: {
13 | PORT: 8080
14 | },
15 | ignore: ['./node_modules/']
16 | })
17 | .on('restart',['test'], function(){
18 | console.log('We have restarted');
19 | })
20 | });
21 |
22 | gulp.task('test', function(){
23 | env({vars:{ENV:'Test'}});
24 | gulp.src(['Tests/singleFunctionTest.js','Tests/cityUpdateTest.js','Tests/activeUpdateTest.js'/*,'Tests/unitUpdateTest.js'*/])
25 | .pipe(gulpMocha({reporter: 'nyan'}));
26 | });
27 |
28 | gulp.task('lint', function () {
29 | return gulp.src(['**/*.js','!node_modules/**','!code graveyard/**','!Tests/**'])
30 | .pipe(eslint())
31 | .pipe(eslint.format());
32 | });
33 |
34 |
--------------------------------------------------------------------------------
/img/brand/expedia.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/img/brand/expedia.jpg
--------------------------------------------------------------------------------
/img/oldImages/expedia.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/img/oldImages/expedia.jpg
--------------------------------------------------------------------------------
/img/oldImages/kaiser-permanente272.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/img/oldImages/kaiser-permanente272.jpg
--------------------------------------------------------------------------------
/img/wallpaper/Kaiser-Permanente-Exterior.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/img/wallpaper/Kaiser-Permanente-Exterior.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "branding",
3 | "version": "1.0.0",
4 | "description": "TP xml deployment app",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "bottleneck": "^2.2.2",
14 | "dotenv": "^5.0.1",
15 | "exceljs": "^0.9.1",
16 | "jsxapi": "^4.1.2",
17 | "lodash": "^4.17.5",
18 | "request": "^2.85.0",
19 | "xmlhttprequest": "^1.8.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | //Application Entry. Command line inut processed by switch command and launches the right function called.
2 |
3 | const log = require('./svrConfig/logger');
4 | const comms = require('./svrConfig/comFunct');
5 |
6 |
7 |
8 | switch (process.argv[2]) {
9 | case null:
10 | log.info("Command incomplete");
11 | return log.info("Please specify your operation. Node command incomplete. Refer to readme for more instructions.");
12 | case "bundle":
13 | log.info("Deploying bundle");
14 | return comms.bundle();
15 | case 'branding':
16 | log.info("Deploy Branding");
17 | return comms.branding();
18 | case 'wallpaper':
19 | log.info("Deploy Wall paper");
20 | return comms.wallpaper();
21 | case 'logs':
22 | log.info("Deploy log collection.");
23 | return comms.logCollection(process.argv[3]);
24 | default:
25 | log.info("Command incomplete");
26 | return log.info("Please specify your operation. Node command incomplete. Refer to readme for more instructions.");
27 | }
28 |
--------------------------------------------------------------------------------
/svrConfig/comFunct.js:
--------------------------------------------------------------------------------
1 | const buildXml = require('../tools/buildXml');
2 | const excel = require('../tools/excel');
3 | const image64 = require('../tools/image64');
4 | const filewatcher = require('../tools/filewatcher');
5 | const _ = require('lodash');
6 | const log = require('./logger');
7 | const Endpoint = require('../tools/endpoint');
8 | const ip = require('../tools/ipaddress');
9 | const collect = require('../tools/collectLogs');
10 |
11 |
12 | var brandingPath = './img/brand/';
13 | var wallPaperPath = './img/wallpaper/';
14 |
15 |
16 | var port = process.env.PORT || "9000";
17 | var filePath = [];
18 | var deployEndpoints = [];
19 | var endpointArray = [];
20 | var backUpObj ={};
21 |
22 | module.exports = {
23 | bundle: function(){
24 | /*STEP 1. build http of host URL and create checksum of backup zip file
25 | STEP 2. Convert CSV of endpoints into array
26 | STEP 3. Build XML payload and deliver payload to each endpoint
27 | */
28 | //URL consists of directory structure and IP address of machine deployed
29 | ip.getIPAddress()
30 | .then(ipString => {
31 | backUpObj.ip = ipString;
32 | return filewatcher.fileWatcherBackupBundle()
33 | })
34 | .then(fileObj => {
35 | backUpObj.cs = fileObj.checksum;
36 | backUpObj.dir = fileObj.fileDir;
37 | return excel.readcsv()
38 | })
39 | .then((endpoints) => {
40 | log.info("Processing branding xml to create new xml file......");
41 | endpointArray = endpoints;
42 | var url = `http://${backUpObj.ip}:${port}/${backUpObj.dir}`;
43 | log.info(url)
44 | return buildXml.bundleXml(backUpObj.cs,url)
45 | })
46 | .then((xmlReturn) => {
47 | log.info("XML deployment starting........ ");
48 | _.forEach(endpointArray, function(ip){
49 | if(!ip) return log.info("Blank endpoint, no files deployed.");
50 | deployEndpoints.push(new Endpoint(ip, xmlReturn, "bundle"));
51 | })
52 | })
53 | .catch(err => {
54 | log.error(err)
55 | });
56 | const httpServer = require('./httpServer');
57 |
58 | },
59 | branding: function(){
60 | /*STEP 1. build base 64 string of image and create file location strings strings
61 | STEP 2. Convert CSV of endpoints into array
62 | STEP 3. Build XML payload and deliver payload to each endpoint
63 | */
64 | log.info("Branding to be deployed.");
65 | Promise.resolve()
66 | .then(() => {
67 | return filewatcher.fileWatcher();
68 | })
69 | .then((files) => {
70 | log.info("Encoding images to base64 for deployment.... ");
71 | return image64.base64encode(files);
72 | })
73 | .then((fileString) => {
74 | //log.info(fileString[1]);
75 | filePath = fileString;
76 | return excel.readcsv()
77 | })
78 | .then((endpoints) => {
79 | log.info("Processing branding xml to create new xml file......");
80 | endpointArray = endpoints;
81 | return buildXml.brandingXml(filePath);
82 | })
83 | .then((xmlReturn) => {
84 | log.info("XML deployment starting........ ");
85 | _.forEach(endpointArray, function(ip){
86 | if(!ip) return log.info("Blank endpoint, no files deployed.");
87 | deployEndpoints.push(new Endpoint(ip, xmlReturn, 'branding'));
88 |
89 |
90 |
91 | })
92 | })
93 | .catch(err => {
94 | log.error(err);
95 | })
96 |
97 | },
98 | logCollection: function(ip){
99 | collect.collectLogs(ip)
100 | .then((response) => {
101 | log.info(response);
102 | })
103 | .catch((err) => {
104 | log.error(err);
105 | })
106 | },
107 | wallpaper: function(){
108 | const dir = "./img/wallpaper/";
109 | if(!dir) return log.error("No file found, please ensure that your wallpaper file to be deployed is in /img/wallpaper.");
110 | return excel.readcsv()
111 | .then((endpoints) => {
112 | log.info("Processing branding xml to create new xml file......");
113 | endpointArray = endpoints;
114 | })
115 | .then(() => {
116 | log.info("XML deployment starting........ ");
117 | _.forEach(endpointArray, function(ip){
118 | if(!ip) return log.info("Blank endpoint, no files deployed.");
119 | deployEndpoints.push(new Endpoint(ip, null, "wallpaper"));
120 | })
121 | })
122 | .catch(err => {
123 | log.error(err)
124 | });
125 | }
126 |
127 | };
--------------------------------------------------------------------------------
/svrConfig/httpServer.js:
--------------------------------------------------------------------------------
1 | //application/zip, application/x-zip-compressed
2 |
3 | const http = require('http');
4 | const url = require('url');
5 | const fs = require('fs');
6 | const path = require('path');
7 | const log = require('./logger');
8 | // you can pass the parameter in the command line. e.g. node static_server.js 3000
9 | const port = process.env.PORT || 9000;
10 | http.createServer(function (req, res) {
11 | log.info(`${req.method} ${req.url}`);
12 | // parse URL
13 | const parsedUrl = url.parse(req.url);
14 | // extract URL path
15 | let pathname = `.${parsedUrl.pathname}`;
16 | // maps file extention to MIME types
17 | const mimeType = {
18 | '.zip': 'application/zip'
19 | };
20 | fs.exists(pathname, function (exist) {
21 | if(!exist) {
22 | // if the file is not found, return 404
23 | res.statusCode = 404;
24 | res.end(`File ${pathname} not found!`);
25 | return;
26 | }
27 | // if is a directory, then look for index.html
28 | if (fs.statSync(pathname).isDirectory()) {
29 | pathname += '/xmlFiles/backupBundle/backup-bundle.zip';
30 | }
31 | // read file from file system
32 | fs.readFile(pathname, function(err, data){
33 | if(err){
34 | res.statusCode = 500;
35 | res.end(`Error getting the file: ${err}.`);
36 | } else {
37 | // based on the URL path, extract the file extention. e.g. .js, .doc, ...
38 | const ext = path.parse(pathname).ext;
39 | // if the file is found, set Content-type and send data
40 | res.setHeader('Content-type', mimeType[ext] || 'text/plain' );
41 | res.end(data);
42 | }
43 | });
44 | });
45 | }).listen(parseInt(port));
46 | log.info(`Server listening on port ${port}`);
--------------------------------------------------------------------------------
/svrConfig/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const env = process.env.NODE_ENV;
5 | const {createLogger, format, transports} = require('winston');
6 | const {combine, timestamp, label, printf, colorize} = format;
7 |
8 |
9 | const myFormat = printf(info => {
10 | return `${info.timestamp} ${info.level}: ${info.message}`;
11 | });
12 |
13 |
14 | const logger =
15 | winston.createLogger({
16 | format: combine(
17 | format.splat(),
18 | colorize({ all: true }),
19 | timestamp(),
20 | myFormat
21 | ),
22 | transports: [
23 | //
24 | // - Write to all logs with level `info` and below to `combined.log`
25 | // - Write all logs error (and below) to `error.log`.
26 | //
27 | new winston.transports.File({ filename: './logs/error.log', level: 'error' }),
28 | new winston.transports.File({ filename: './logs/combined.log' })
29 | ],
30 | exceptionHandlers: [
31 | new winston.transports.File( {
32 | filename: 'logs/exceptions.log'
33 | } ),
34 | new winston.transports.Console( {
35 | colorize: true
36 | } ),
37 | ]
38 | });
39 |
40 | //
41 | // If we're not in production then log to the `console` with the format:
42 | // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
43 | //
44 | if (env !== 'production') {
45 | logger.add(new winston.transports.Console());
46 | }
47 |
48 | //logger.info('Hello, this is a logging event with a custom pretty print', { 'foo': 'bar' });
49 | //logger.info('Hello, this is a logging event with a custom pretty print2', { 'foo': 'bar' });
50 |
51 | module.exports = logger;
52 |
53 |
--------------------------------------------------------------------------------
/tools/buildXml.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | brandingXml: function(base64){
4 | return new Promise(function(resolve){
5 | var base64Brand = base64[0];
6 | var base64wp = base64[1];
7 | var xml2 = `
8 |
9 |
10 |
11 | HalfwakeBranding
12 | ${base64Brand}
13 |
14 |
15 | Branding
16 | ${base64Brand}
17 |
18 |
19 | HalfwakeBackground
20 | ${base64wp}
21 |
22 |
23 |
24 | `;
25 |
26 | resolve(xml2)
27 |
28 | })
29 |
30 | },
31 | inRoomXml: function(){
32 | return new Promise(function(resolve) {
33 |
34 | })
35 | },
36 | macroXml: function(){
37 | return new Promise(function(resolve){
38 |
39 | })
40 |
41 | },
42 | bundleXml: function(checksum, url){
43 | return new Promise(function(resolve){
44 | var xml2 = `
45 |
46 |
47 |
48 | ${url}
49 | ${checksum}
50 |
51 |
52 |
53 | `;
54 | resolve(xml2)
55 | })
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/tools/collectLogs.js:
--------------------------------------------------------------------------------
1 | //download logs from a endpoint
2 |
3 | require('dotenv').config();
4 | const request = require('request');
5 | const fs = require('fs');
6 | const username = process.env.TPADMIN || "admin";
7 | const password = process.env.TPADMINPWD || "password";
8 |
9 | module.exports = {
10 | collectLogs : function(ip) {
11 | return new Promise(function (resolve) {
12 | const url = `http://${ip}/api/logs/download`;
13 | const r = request.get(url).auth(username, password, false);
14 | r.on('response', function (res) {
15 | res.pipe(fs.createWriteStream('./endpointLogs/' + res.headers.date + '.' + res.headers['content-type'].split('/')[1]))
16 | res.on('end', function() { resolve("write complete") });
17 | })
18 | })
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/tools/endpoint.js:
--------------------------------------------------------------------------------
1 | //creates main endpoint object for TP endpoint
2 | /*
3 | multipart/form-data
4 | */
5 |
6 | require('dotenv').config();
7 | const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
8 |
9 | const util = require('util');
10 | const EventEmitter = require('events').EventEmitter;
11 | const TpXapi = require('./tpXapi');
12 | const log = require('../svrConfig/logger');
13 | const request = require('request');
14 | const fs = require('fs');
15 |
16 | //pass in object versus single values
17 | function Endpoint(ip,xml,type){
18 | this.ipAddress = ip;
19 | this.password = process.env.TPADMINPWD;
20 | this.username = process.env.TPADMIN;
21 | this.url = `http://${ip}/putxml`;
22 | this.wallpaperUrl = `http://${ip}/api/wallpapers`;
23 | this.version = '';
24 | this.xml = xml;
25 | this.type = type;
26 | this.init();
27 | }
28 |
29 | util.inherits(Endpoint,EventEmitter);
30 |
31 | Endpoint.prototype.init = function(){
32 | var self = this;
33 | //insert version checker to work out best thing to deploy. Should check version for back-bundles as well.
34 | self.firmwareCheck()
35 | .then((data) => {
36 | var version = data.version.slice(2,7);
37 | var tpType = data.type;
38 | log.info(version + tpType);
39 | if(self.type==="branding") {
40 | if (tpType === "SX10") {
41 | return self.postWallpaper();
42 | } else {
43 | switch (true) {
44 | case (/(^)9.3( |.|$)/).test(version):
45 | return self.deployXml();
46 | case (/(^)9.2( |.|$)/).test(version):
47 | return self.deployXml();
48 | case (/(^)9.1( |.|$)/).test(version):
49 | return self.postWallpaper();
50 | case (/(^)7( |.|$)/).test(version):
51 | return self.postWallpaper();
52 | default:
53 | return log.info("Something went wrong with firmware check");
54 | }
55 | }
56 | }else if(self.type==="wallpaper"){
57 | return self.postWallpaper();
58 | }else{
59 | switch (true) {
60 | case (/(^)9.3( |.|$)/).test(version):
61 | return self.deployXml();
62 | default:
63 | return log.info("Endpoint not compatible with bundling feature. Must be CE9.3 or later: " +self.ipAdress+' : '+self.version);
64 | }
65 | }
66 |
67 | })
68 | .catch(err => {
69 | log.error(err);
70 | })
71 |
72 | };
73 | //check what version of software is on the endpoint
74 | Endpoint.prototype.firmwareCheck = function (){
75 | var self = this;
76 | return new Promise(function(resolve){
77 | log.info("firmwareCheck launched ...");
78 |
79 | var ep = {
80 | "password": self.password,
81 | "username": self.username,
82 | "ipAddress" : self.ipAddress
83 | };
84 | var videoCodec = new TpXapi(ep);
85 | videoCodec.getEndpointData()
86 | .then((endpoint) => {
87 | return resolve(endpoint);
88 | })
89 | .catch(err => {
90 | log.error(err);
91 | });
92 |
93 |
94 | })
95 |
96 | };
97 |
98 | Endpoint.prototype.deployXml = function(){
99 | var self = this;
100 | var mimeType = "text/xml";
101 | const xmlHttp = new XMLHttpRequest();
102 | xmlHttp.onreadystatechange = function() {
103 |
104 | if (xmlHttp.readyState === 4) {
105 | log.info("State: " + this.readyState);
106 |
107 |
108 | if (this.readyState === 4) {
109 | log.info(null,"Complete.\nBody length: " + this.responseText.length);
110 | log.info("Body:\n" + this.responseText+xmlHttp.DONE);
111 | if(xmlHttp.DONE === 4 && this.responseText.length > 1) return log.info("Package Deployed to "+self.ipAddress);
112 | }
113 |
114 | }
115 | }
116 | xmlHttp.open('POST', self.url, true, self.username, self.password);
117 | xmlHttp.setRequestHeader('Content-Type', mimeType);
118 | xmlHttp.withCredentials = true;
119 | xmlHttp.send(this.xml);
120 | };
121 |
122 | Endpoint.prototype.postWallpaper = function(){
123 | log.info("Posting wall paper");
124 | const self = this;
125 | const dir = "./img/wallpaper/";
126 | var fileName = fs.readdirSync('./img/wallpaper/');
127 | if(!dir) log.error("No file found");
128 | var fileString = dir+fileName;
129 | log.info(fileString);
130 | var formData = {
131 |
132 | file: {
133 | value: fs.createReadStream(fileString),
134 | options: {
135 | filename: fileName[0],
136 | contentType: 'image/jpeg'
137 | }
138 | }
139 | };
140 | log.info(JSON.stringify(formData));
141 | var r = request.post({url:`http://${self.ipAddress}/api/wallpapers`, formData: formData},function optionalCallback(err, httpResponse, body) {
142 | if (err) {
143 | return console.error('upload failed:', err);
144 | }
145 | console.log('Upload successful! Server responded with:', body);
146 | }).auth(self.username, self.password, false);
147 |
148 |
149 |
150 | };
151 |
152 |
153 | module.exports = Endpoint;
154 |
--------------------------------------------------------------------------------
/tools/excel.js:
--------------------------------------------------------------------------------
1 | //module for reading CSV file downloaded from Spark for uploading bulk TP endpoints - needs work on adding validy of CSV format
2 |
3 | var Excel = require('exceljs');
4 | var fs = require('fs');
5 | var workbook = new Excel.Workbook();
6 | var log = require('../svrConfig/logger');
7 |
8 |
9 |
10 |
11 | module.exports = {
12 | readcsv: function(){
13 | return new Promise(function(resolve, reject){
14 | var endpoints = [];
15 | var filename;
16 | var fileDir = './endpoints/';
17 | var file = fs.readdirSync(fileDir);
18 | log.info(file);
19 | filename = fileDir+file;
20 |
21 | log.info("Reading CSV, creating endpoint array for deployment...")
22 |
23 | workbook.csv.readFile(filename)
24 | .then(function(worksheet) {
25 |
26 | for(var i = 0; i= 1) {
17 | // this single interface has multiple ipv4 addresses
18 | resolve(iface.address);
19 | } else {
20 | // this interface has only one ipv4 adress
21 | resolve(iface.address);
22 | }
23 | ++alias;
24 | });
25 | });
26 | })
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/tools/tpXapi.js:
--------------------------------------------------------------------------------
1 | const util = require('util');
2 | const EventEmitter = require('events').EventEmitter;
3 | const log = require('../svrConfig/logger');
4 | const jsxapi = require('jsxapi');
5 |
6 | //pass in object versus single values
7 | function TPXapi(endpoint){
8 | this.endpoint = endpoint;
9 | this.xapi;
10 | this.endpointVersion;
11 | this.endpointType;
12 |
13 | };
14 |
15 | util.inherits(TPXapi,EventEmitter);
16 |
17 | //force update of data from endpoint
18 | TPXapi.prototype.getEndpointData = function(){
19 | return new Promise((resolve, reject) => {
20 | const self = this;
21 | return self.endpointUpdate()
22 | .then(() => {
23 | let endpoint = {
24 | version : self.endpointVersion,
25 | type : self.endpointType
26 | }
27 | return resolve(endpoint);
28 | })
29 | .catch(err => {
30 | log.error(err)
31 | })
32 | });
33 | };
34 |
35 |
36 | TPXapi.prototype.endpointUpdate = function(){
37 | const self = this;
38 | return self.connect()
39 | .then((version) => {
40 | log.info(version);
41 | return self.checkVersion();
42 | })
43 | .then((status) => {
44 | log.info(status);
45 | return self.checkType()
46 | })
47 | .then((type) => {
48 | log.info("The type is: "+type);
49 | return self.closeConnect()
50 | })
51 | .catch((err) => {
52 | log.error(err);
53 | })
54 | }
55 |
56 | //connect to ssh service on endpoints
57 | TPXapi.prototype.connect = function() {
58 | var self = this;
59 | log.info(JSON.stringify(self.endpoint));
60 | return new Promise((resolve, reject) => {
61 | self.xapi = jsxapi.connect('ssh://' + self.endpoint.ipAddress, {
62 | username: self.endpoint.username,
63 | password: self.endpoint.password
64 | });
65 | resolve ("Connection open")
66 | .catch ((err) => {
67 | reject (log.error(err));
68 | });
69 | });
70 | }
71 |
72 | TPXapi.prototype.checkVersion = function(){
73 | //SystemUnit Software Version
74 | const self = this;
75 | return new Promise((resolve, reject) => {
76 | return self.xapi.status
77 | .get('SystemUnit Software Version')
78 | .then((version) => {
79 | self.endpointVersion = version;
80 | resolve(version);
81 | })
82 | .catch(err => reject(err));
83 | })
84 | };
85 | TPXapi.prototype.checkType = function(){
86 | //SystemUnit type
87 | log.info("info: Checking system type.")
88 | const self = this;
89 | return new Promise((resolve, reject) => {
90 | return self.xapi.status
91 | .get('SystemUnit ProductPlatform')
92 | .then((type) => {
93 | self.endpointType = type;
94 | resolve(type);
95 | })
96 | .catch(err => reject(err));
97 | })
98 | };
99 |
100 |
101 | //close ssh connection
102 | TPXapi.prototype.closeConnect = function(){
103 | const self = this;
104 | return new Promise((resolve, reject) => {
105 | log.info("xapi session closed.");
106 | self.connectedStatus = "false";
107 | resolve (self.xapi.close());
108 |
109 | return self;
110 |
111 | })
112 | };
113 |
114 |
115 | module.exports = TPXapi;
--------------------------------------------------------------------------------
/xmlFiles/backupBundle/backup-bundle.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voipnorm/CiscoTPCustomXML/f603f3b40f6093c01faaaaf85f143382e2323615/xmlFiles/backupBundle/backup-bundle.zip
--------------------------------------------------------------------------------
/xmlFiles/macros/proximityMacro.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Macro companion to the Ultrasound Control
3 | * - lets users toggle Proximity Mode to On/Off
4 | * - displays the current MaxVolume level
5 | */
6 |
7 | const xapi = require('xapi');
8 | const proximityID = 'ProximityOnOff';
9 | const textBoxId = 'textBoxProximity';
10 |
11 | // Change proximity mode to "On" or "Off"
12 | function switchProximityMode(mode) {
13 | console.debug(`switching proximity mode to: ${mode}`);
14 |
15 | xapi.config.set('Proximity Mode', mode)
16 | .then(() => {
17 | console.info(`turned proximity mode: ${mode}`)
18 | })
19 | .catch((err) => {
20 | console.error(`could not turn proximity mode: ${mode}`)
21 | })
22 | }
23 |
24 | // React to UI events
25 | function onGui(event) {
26 | // Proximity Mode Switch
27 | if ((event.Type === 'changed') && (event.WidgetId === proximityID||event.WidgetId === "proximity_toggle")) {
28 | switchProximityMode(event.Value)
29 | return;
30 | }
31 | }
32 | xapi.event.on('UserInterface Extensions Widget Action', onGui);
33 |
34 |
35 | //
36 | // Proximity Services Availability
37 | //
38 |
39 | // Update Toogle if proximity mode changes
40 | function updateProximityToggle(mode) {
41 | console.debug(`switching toggle to ${mode}`)
42 |
43 | xapi.command("UserInterface Extensions Widget SetValue", {
44 | WidgetId: proximityID,
45 | Value: mode
46 | })
47 | xapi.command("UserInterface Extensions Widget SetValue", {
48 | WidgetId: "proximity_toggle",
49 | Value: mode
50 | })
51 | }
52 | xapi.config.on("Proximity Mode", mode => {
53 | console.log(`proximity mode changed to: ${mode}`)
54 |
55 | // Update toggle
56 | // [WORKAROUND] Configuration is On or Off, needs to be turned to lowercase
57 | updateProximityToggle(mode.toLowerCase());
58 | textBoxUpdate(mode);
59 | })
60 |
61 | // Refresh Toggle state
62 | function refreshProximityToggle() {
63 | xapi.status.get("Proximity Services Availability")
64 | .then(availability => {
65 | console.debug(`current proximity mode is ${availability}`)
66 | switch (availability) {
67 | case 'Available':
68 | updateProximityToggle('on');
69 | textBoxUpdate('On');
70 | return;
71 |
72 | case 'Disabled':
73 | default:
74 | updateProximityToggle('off')
75 | textBoxUpdate('Off')
76 | return;
77 | }
78 | })
79 | .catch((err) => {
80 | console.error(`could not read current proximity mode, err: ${err.message}`)
81 | })
82 | }
83 | //update text box to show proximity status
84 | function textBoxUpdate(stringValue){
85 | xapi.command('UserInterface Extensions Widget SetValue', {
86 | WidgetId: textBoxId,
87 | Value: "Proximity "+stringValue,
88 | });
89 | }
90 | // Initialize at widget deployment
91 | xapi.event.on('UserInterface Extensions Widget LayoutUpdated', (event) => {
92 | console.debug("layout updated, let's refresh our toogle");
93 | refreshProximityToggle()
94 | });
--------------------------------------------------------------------------------
/xmlFiles/readme.txt:
--------------------------------------------------------------------------------
1 | Use this folder to stash backup-bundle, roomControl xml and Macro files that need to be deployed to your endpoints.
2 | The application will suck up these files into the correct XML format to deploy to your endpoints.
3 |
4 | Backup bundles file currently in file is example only, make sure to delete and replace with your own.
5 |
6 | In the case of the backup-bdunle deploymnet in CE9.3 a checksum will be created and allplication provides a
7 | HTTP server to allow endpoints to download bundle package.
8 |
9 | The proximity files are here as an working example. If you do not want this deployed to your endpoints make sure to remove before deployment.
--------------------------------------------------------------------------------
/xmlFiles/roomControls/proximityButton.xml:
--------------------------------------------------------------------------------
1 |
2 | 1.5
3 |
4 | Proximity
5 | Statusbar
6 | Proximity
7 | 1
8 | #A866FF
9 | Proximity
10 |
11 | Page
12 |
13 | Proximity
14 |
15 | proximity_toggle
16 | ToggleButton
17 | size=1
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------