Wiki source code of Demo for Smart Office, Factory

Version 33.1 by Hera Guo on 2024/11/06 14:10

Show last authors
1 **Table of Contents:**
2
3 {{toc/}}
4
5
6
7
8 = 1. About this demo =
9
10 This demo is to show the installation for various sensors in Dragino Office, Dragino Facotry & ThingsEye Office. It covers various types of sensors such as Temperature, Humidity, CO2, Water Flow, Vibration & many many.
11
12 User can check this [[Public Share Link>>https://thingseye.io/dashboard/d17f70f0-6b5f-11ef-a329-6fb88c149adb?publicId=33180810-5c40-11ef-a329-6fb88c149adb ]] and see the dash board for this demo. The dash board keeps updating, while the main structure will keep the same. It has **Three Level DashBoard **as decribe below.
13
14 * **First Level - Overview for all branches**: This dashboard shows all branches overview status and location.
15 * **Second Level - Branch Level**: This dashboard shows all sensors installation and status in the selected branch.
16 * **Third Level - Sensor Level**: This dashboard shows the detail reading for a specify sensor
17
18 [[image:Level1.png||height="133" width="298"]] [[image:Arrow.png||height="27" width="51"]] [[image:Level2.png||height="134" width="264"]][[image:Arrow.png||height="27" width="51"]] [[image:2024-09-26 23-47-06.png||height="130" width="256"]]
19
20
21 The rest of this chapter will provide the introduction for how to set up similiar solution.
22
23
24 = 2.Basic configuration instructions =
25
26 When you start a complex IoT project, you first need to learn some basic configuration methods for ThingsEye.
27
28 Here are some instructions you need to know:
29
30 Dashboard creation and some basic configurations:[[https:~~/~~/wiki.thingseye.io/xwiki/bin/view/Main/How%20to%20import%20and%20use%20the%20dashboard%3F/#H3.2.2.1CreatA0alarm>>https://wiki.thingseye.io/xwiki/bin/view/Main/How%20to%20import%20and%20use%20the%20dashboard%3F/#H3.2.2.1CreatA0alarm]]
31
32 Rule chain creation:[[https:~~/~~/wiki.thingseye.io/xwiki/bin/view/Main/Basic%20configuration%20of%20rule%20chains>>https://wiki.thingseye.io/xwiki/bin/view/Main/Basic%20configuration%20of%20rule%20chains/]]
33
34 Devices connected to thingseye:[[https:~~/~~/wiki.thingseye.io/xwiki/bin/view/Main/How%20to%20connect%20my%20devices%20to%20ThingsEye%3F/>>https://wiki.thingseye.io/xwiki/bin/view/Main/How%20to%20connect%20my%20devices%20to%20ThingsEye%3F/]]
35
36 = 3.overview =
37
38 == 3.1 MHierarchical architectureore features ==
39
40 Before we start a project, we first need to understand the organizational structure of the project. Only with a clear outline can our project construction process be smoother
41
42 **Assets:**Dragino Office  、Dragino Factory
43
44 **Devices:**
45
46 Dragino Factory:temperature and humidity measurement×7、Gateway×1
47
48 Dragino Office:temperature and humidity measurement×2、Air quality measurement×4
49
50 == 3.2 Dashboard architecture ==
51
52 In this demo, the dashboard is divided into three layers, namely: home page, asset, and device.
53
54 **home page:**It includes three parts: map, asset list, and all alarm. From this interface, you can see how many factories, offices, and so on there are
55
56 **asset:**It includes three parts: asset map, device list, and asset alarm. From this interface, you can see how many sensors are deployed in the office or project, where they are located, and their alarm status
57
58 **device:**This section displays the specific information collected by the device, and different types of sensors have different display interfaces
59
60 [[image:屏幕截图 2024-11-04 134645.png]]
61
62 First floor:
63
64 [[image:1730702565889-204.png||height="771" width="1445"]]
65
66 Second floor:
67
68 [[image:1730702622551-808.png||height="756" width="1450"]]
69
70 Third floor:
71
72 [[image:1730702656725-496.png||height="775" width="1455"]]
73
74 [[image:1730702814435-805.png||height="797" width="1458"]]
75
76
77 [[image:1730702688377-367.png||height="770" width="1462"]]
78
79 * How many types of devices do you need, how many layers of third level dashboards you need to create.
80
81 == 3.3 Alarm rules ==
82
83 High Temperature、Low Temperature、High humidity、Low humidity、Low voltage、Device Disconnected
84
85 [[image:屏幕截图 2024-11-04 135045.png]]
86
87 = 4.configuration details =
88
89 After understanding the architecture and layering of the complete project, we can start configuring it
90
91 == 4.1 Dashboard configuration details ==
92
93 === 4.1.1.Data source (Entity aliases) ===
94
95 detail:Obtain data based on dashboard status
96
97 [[image:1730709424998-915.png||height="729" width="1436"]]
98
99 Alarm:Obtain alarm information
100
101 [[image:1730709479828-595.png||height="696" width="1435"]]
102
103 Dragino&GXHL,Ltd:Obtain data through asset types
104
105 [[image:1730709511861-439.png||height="714" width="1435"]]
106
107 Selected Supermarket:Retrieve devices by device type
108
109 [[image:1730709527720-418.png||height="751" width="1433"]]
110
111 Supermarket Devices:Obtain data through device type
112
113 [[image:1730709555797-383.png||height="726" width="1434"]]
114
115 LHT65N Device:Obtain data based on device type
116
117 [[image:1730857191863-514.png||height="725" width="1433"]]
118
119 === 4.1.2.Page Configuration ===
120
121 ==== 4.1.2.1、Configure the interface of the third layer Davies. ====
122
123 ==== 4.1.2.2、Configure the interface of the second layer asset ====
124
125 ===== 4.1.2.2.1 Equipment distribution diagram: =====
126
127 **Data:**
128
129 [[image:1730770392454-317.png||height="745" width="1439"]]
130
131 **Appearannce:**In this module, we need to arrange our devices in the corresponding positions and use icons to display our devices. Therefore, in the Appearance interface, we need to configure them
132
133 **Tooltip function:**This module displays the current information of the device
134
135 [[image:1730857537965-184.png]]
136
137 {{code language="none"}}
138 var msg = data
139 if(msg.Label=="gateway" && msg.type == "gateway"){
140 var stauts
141 if (msg.gatewaystauts=="true"){
142 stauts = "Connect"
143 }
144 else{
145 stauts = "Disconnected"
146 }
147 var str = "<b>"+msg.entityName+"</b><br/><b>"+stauts+"</b><br/>"
148 return str
149 }
150 else if(msg.type=="gxhl01" && msg.Label!="gateway"){
151 var str = "<b>"+msg.entityName+"</b><br/><b>"+msg.Label+"</b><br/><b>Bat:</b>"+msg.BatV+"V<br/><b>Temperature:</b>"+ msg.TempC_SHT+ "°C<br/><b>Humidity:</b>"+msg.Hum_SHT+"%"
152 return str
153 }
154 else{
155 var str = "<b>"+msg.entityName+"</b><br/><b>"+msg.Label+"</b><br/><b>Bat:</b>"+msg.BatV+"V<br/><b>Temperature:</b>"+ msg.temperature+ "°C<br/><b>Humidity:"+msg.humidity+"%"+"</b><br/>"+
156 "<b>Co2:"+msg.co2+"</b></br><b>Air_Pressure:"+msg.air_pressure
157
158 return str
159 }
160 {{/code}}
161
162 (% class="wikigeneratedid" id="HMarkerimagefunctionFF1A" %)
163 **Marker image function:**This module can display different icons based on different types of sensors and their status to achieve its functionality
164
165 (% class="wikigeneratedid" %)
166 [[image:1730857750749-240.png]]
167
168 {{code language="none"}}
169 var res
170 var msg = data
171 if(msg.Label=="gateway" && msg.type=="gateway"){
172 if (msg.gatewaystauts == "true"){
173 res = {
174 url: images[3],
175 size: 40
176 }
177 }
178 else{
179 res = {
180 url: images[2],
181 size: 40
182 }
183 }}
184 else if(msg.Label!="gateway" && msg.type=="gxhl01" ){
185 if (msg.active=="false"){
186 res = {
187 url: images[1],
188 size: 40
189 }}
190 else{
191 res = {
192 url: images[0],
193 size: 40
194 }
195 }
196 }
197 else if(msg.type=="LWL02"){
198 if (msg.WATER_LEAK_STATUS=="0"){
199 res = {
200 url: images[6],
201 size: 40
202 }}
203 else{
204 res = {
205 url: images[7],
206 size: 40
207 }
208 }
209 }
210 else if(msg.type=="LDS02"){
211 if (msg.DOOR_OPEN_STATUS=="0"){
212 res = {
213 url: images[5],
214 size: 40
215 }}
216 else{
217 res = {
218 url: images[8],
219 size: 40
220 }
221 }
222 }
223 else if(msg.type=="LDS12"){
224 res = {
225 url: images[10],
226 size: 40
227 }}
228 else if(msg.type=="SE01"){
229 res = {
230 url: images[9],
231 size: 40
232 }}
233 else if(msg.type=="PB01"){
234 res = {
235 url: images[11],
236 size: 40
237 }}
238 else if(msg.type=="S31b"){
239 res = {
240 url: images[12],
241 size: 40
242 }}
243 else if(msg.type=="LHT65N"){
244 res = {
245 url: images[13],
246 size: 40
247 }}
248 else{
249 res = {
250 url: images[4],
251 size: 40
252 }
253 }
254 return res;
255 {{/code}}
256
257 (% class="wikigeneratedid" id="H" %)
258 [[image:1730770875793-351.png]]**Actions:**We need to implement the function of entering the details interface through the corresponding device icon, so in this module, we need to add actions to achieve redirection
259
260 {{code language="none"}}
261 var entitySubType;
262 var $injector = widgetContext.$scope.$injector;
263 $injector.get(widgetContext.servicesMap.get('entityService')).getEntity(entityId.entityType, entityId.id)
264 .subscribe(function(data) {
265 entitySubType = data.type;
266 console.log(entitySubType)
267 if (entitySubType == 'gateway') {
268 openDashboardStates('gateway_detail');
269 } else if (entitySubType == 'gxhl01') {
270 openDashboardStates('detail');
271 }
272 else if(entitySubType == 'AQS01-dragino-office'){
273 openDashboardStates("aqs01_detail")
274 }
275 else if (entitySubType == 'LDS12') {
276 openDashboardStates('lds12_detail');
277 }
278 else if (entitySubType == 'LDS02') {
279 openDashboardStates('lds02_detail');
280 }
281 else if (entitySubType == 'SE01') {
282 openDashboardStates('se01_detail');
283 }
284 else if (entitySubType == 'PB01') {
285 openDashboardStates('pb01_detail');
286 }
287 else if (entitySubType == 'LWL02') {
288 openDashboardStates('lwl02_detail');
289 }
290 else if (entitySubType == 'LPS8N') {
291 openDashboardStates('lps8n_detail');
292 }
293 else if (entitySubType == 'LHT65N') {
294 openDashboardStates('lht65n_detail');
295 }
296 else if (entitySubType == 'S31b') {
297 openDashboardStates('s31b_detail');
298 }
299 });
300
301 function openDashboardStates(statedId) {
302 var stateParams = widgetContext.stateController.getStateParams();
303 var params = {
304 entityId: entityId,
305 entityName: entityName
306 };
307
308 if (stateParams.city) {
309 params.city = stateParams.city;
310 }
311
312 widgetContext.stateController.openState(statedId, params, false);
313 }
314
315 {{/code}}
316
317 [[image:1730771103096-522.png]]
318
319 ===== 4.1.2.2.2 Device List =====
320
321 (% class="wikigeneratedid" id="HDataFF1A" %)
322 **Data:**
323
324 [[image:1730771199343-553.png]]
325
326 **Actions:**Equipment distribution diagram: In this module, functions need to be implemented such as adding devices, editing devices, deleting devices, and jumping to the device details page. Therefore, the following actions need to be added:
327
328 [[image:1730771228766-212.png]]
329
330 (% class="wikigeneratedid" id="HEditdeviceFF1A" %)
331 Edit device:Implementation function: Device editing
332
333 [[image:1730771256045-238.png]]
334
335 {{code language="none"}}
336 let $injector = widgetContext.$scope.$injector;
337 let customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));
338 let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));
339 let attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));
340
341 openEditDeviceDialog();
342
343 function openEditDeviceDialog() {
344 customDialog.customDialog(htmlTemplate, EditDeviceDialogController).subscribe();
345 }
346
347 function EditDeviceDialogController(instance) {
348 let vm = instance;
349
350 vm.device = null;
351 vm.attributes = {};
352
353 vm.editDeviceFormGroup = vm.fb.group({
354 deviceName: ['', [vm.validators.required]],
355 deviceType: ['', [vm.validators.required]],
356 deviceLabel: [''],
357 attributes: vm.fb.group({
358 latitude: [null],
359 longitude: [null]
360 })
361 });
362
363 vm.cancel = function() {
364 vm.dialogRef.close(null);
365 };
366
367 vm.save = function() {
368 vm.editDeviceFormGroup.markAsPristine();
369 if (vm.editDeviceFormGroup.get('deviceType').value !== vm.device.type) {
370 delete vm.device.deviceProfileId;
371 }
372 vm.device.name = vm.editDeviceFormGroup.get('deviceName').value,
373 vm.device.type = vm.editDeviceFormGroup.get('deviceType').value,
374 vm.device.label = vm.editDeviceFormGroup.get('deviceLabel').value
375 deviceService.saveDevice(vm.device).subscribe(
376 function () {
377 saveAttributes().subscribe(
378 function () {
379 widgetContext.updateAliases();
380 vm.dialogRef.close(null);
381 }
382 );
383 }
384 );
385 };
386
387 getEntityInfo();
388
389 function getEntityInfo() {
390 deviceService.getDevice(entityId.id).subscribe(
391 function (device) {
392 attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE',
393 ['latitude', 'longitude']).subscribe(
394 function (attributes) {
395 for (let i = 0; i < attributes.length; i++) {
396 vm.attributes[attributes[i].key] = attributes[i].value;
397 }
398 vm.device = device;
399 vm.editDeviceFormGroup.patchValue(
400 {
401 deviceName: vm.device.name,
402 deviceType: vm.device.type,
403 deviceLabel: vm.device.label,
404 attributes: {
405 latitude: vm.attributes.latitude,
406 longitude: vm.attributes.longitude
407 }
408 }, {emitEvent: false}
409 );
410 }
411 );
412 }
413 );
414 }
415
416 function saveAttributes() {
417 let attributes = vm.editDeviceFormGroup.get('attributes').value;
418 let attributesArray = [];
419 for (let key in attributes) {
420 attributesArray.push({key: key, value: attributes[key]});
421 }
422 if (attributesArray.length > 0) {
423 return attributeService.saveEntityAttributes(entityId, 'SERVER_SCOPE', attributesArray);
424 } else {
425 return widgetContext.rxjs.of([]);
426 }
427 }
428 }
429 {{/code}}
430
431 (% class="wikigeneratedid" id="H" %)
432 Delete device:Implementation function: Device deletion
433
434 [[image:1730771318657-502.png]]
435
436 {{code language="none"}}
437 let $injector = widgetContext.$scope.$injector;
438 let dialogs = $injector.get(widgetContext.servicesMap.get('dialogs'));
439 let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));
440
441 openDeleteDeviceDialog();
442
443 function openDeleteDeviceDialog() {
444 let title = "Are you sure you want to delete the device " + entityName + "?";
445 let content = "Be careful, after the confirmation, the device and all related data will become unrecoverable!";
446 dialogs.confirm(title, content, 'Cancel', 'Delete').subscribe(
447 function (result) {
448 if (result) {
449 deleteDevice();
450 }
451 }
452 );
453 }
454
455 function deleteDevice() {
456 deviceService.deleteDevice(entityId.id).subscribe(
457 function () {
458 widgetContext.updateAliases();
459 }
460 );
461 }
462
463 {{/code}}
464
465 jump:Implementation function: Jump to the device details page
466
467 [[image:1730771386258-676.png]]
468
469 {{code language="none"}}
470 console.log(entityName)
471 var entitySubType;
472 var $injector = widgetContext.$scope.$injector;
473 //console.log($injector)
474 $injector.get(widgetContext.servicesMap.get('entityService')).getEntity(entityId.entityType, entityId.id)
475 .subscribe(function(data) {
476 console.log(data)
477 entitySubType = data.type;
478 console.log(entitySubType)
479 if (entitySubType == 'AQS01-dragino-office') {
480 openDashboardStates('aqs01_detail');
481 }else if (entitySubType == 'gateway') {
482 openDashboardStates('gateway_detail');
483 } else if (entitySubType == 'gxhl01') {
484 openDashboardStates('detail');
485
486 } else if (entitySubType == 'tank-type1') {
487 openDashboardStates('test1');
488 }
489 else if (entitySubType == 'LDS12') {
490 openDashboardStates('lds12_detail');
491 }
492 else if (entitySubType == 'LDS02') {
493 openDashboardStates('lds02_detail');
494 }
495 else if (entitySubType == 'SE01') {
496 openDashboardStates('se01_detail');
497 }
498 else if (entitySubType == 'PB01') {
499 openDashboardStates('pb01_detail');
500 }
501 else if (entitySubType == 'LWL02') {
502 openDashboardStates('lwl02_detail');
503 }
504 else if (entitySubType == 'LPS8N') {
505 openDashboardStates('lps8n_detail');
506 }
507 else if (entitySubType == 'LHT65N') {
508 openDashboardStates('lht65n_detail');
509 }
510 else if (entitySubType == 'S31b') {
511 openDashboardStates('s31b_detail');
512 }
513 });
514
515 function openDashboardStates(statedId) {
516 var stateParams = widgetContext.stateController.getStateParams();
517 //console.log(stateParams)
518 var params = {
519 entityId: entityId,
520 entityName: entityName
521 };
522 widgetContext.stateController.updateState(statedId, params, false);
523 }
524 {{/code}}
525
526 (% class="wikigeneratedid" id="H-1" %)
527 Add device:Implementation function: Add device
528
529 [[image:1730771441589-122.png]]
530
531 {{code language="none"}}
532 let $injector = widgetContext.$scope.$injector;
533 let customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));
534 let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));
535 let attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));
536
537 openAddDeviceDialog();
538
539 function openAddDeviceDialog() {
540 customDialog.customDialog(htmlTemplate, AddDeviceDialogController).subscribe();
541 }
542
543 function AddDeviceDialogController(instance) {
544 let vm = instance;
545
546 vm.addDeviceFormGroup = vm.fb.group({
547 deviceName: ['', [vm.validators.required]],
548 deviceType: ['', [vm.validators.required]],
549 deviceLabel: [''],
550 attributes: vm.fb.group({
551 latitude: [null],
552 longitude: [null]
553 })
554 });
555
556 vm.cancel = function() {
557 vm.dialogRef.close(null);
558 };
559
560 vm.save = function() {
561 vm.addDeviceFormGroup.markAsPristine();
562 let device = {
563 name: vm.addDeviceFormGroup.get('deviceName').value,
564 type: vm.addDeviceFormGroup.get('deviceType').value,
565 label: vm.addDeviceFormGroup.get('deviceLabel').value
566 };
567 deviceService.saveDevice(device).subscribe(
568 function (device) {
569 saveAttributes(device.id).subscribe(
570 function () {
571 widgetContext.updateAliases();
572 vm.dialogRef.close(null);
573 }
574 );
575 }
576 );
577 };
578
579 function saveAttributes(entityId) {
580 let attributes = vm.addDeviceFormGroup.get('attributes').value;
581 let attributesArray = [];
582 for (let key in attributes) {
583 attributesArray.push({key: key, value: attributes[key]});
584 }
585 if (attributesArray.length > 0) {
586 return attributeService.saveEntityAttributes(entityId, "SERVER_SCOPE", attributesArray);
587 } else {
588 return widgetContext.rxjs.of([]);
589 }
590 }
591 }
592 {{/code}}
593
594 ==== ====
595
596 ===== **4.1.2.2.3 Asset Alarm:** =====
597
598 **Data:**
599
600 [[image:1730771504586-433.png]]
601
602 ==== 4.1.2.3、Configure the first layer menu interface ====
603
604 ===== 4.1.2.3.1 **Map:** =====
605
606 **Data:**
607
608 [[image:1730710271230-716.png||height="729" width="1427"]]
609
610 Actions:The map interface has two actions, among which Select supermarket can refresh the device list and related alarms on the right side to enter the location, and Supermarket_detail can jump to the second level physical interface to view the details of the location based on the selected location
611
612 [[image:1730710850458-781.png||height="770" width="1429"]]
613
614 Select supermarket:Implementation function: Refresh the side page
615
616 {{code language="none"}}
617 var params = widgetContext.stateController.getStateParams();
618 var selectedSupermarket = params['selectedSupermarket'];
619 if (selectedSupermarket && selectedSupermarket.entityId.id === entityId.id) {
620 params['selectedSupermarket'] = null;
621 } else {
622 params['selectedSupermarket'] = { entityId: entityId, entityName: entityName, entityLabel: entityLabel };
623 }
624 widgetContext.stateController.updateState(null, params);
625 {{/code}}
626
627 [[image:1730710875401-848.png||height="767" width="1429"]]
628
629 Supermarket_detail:Implementation function: Jump to the asset details page
630
631 {{code language="none"}}
632 var params = JSON.parse(JSON.stringify(widgetContext.stateController.getStateParams()));
633 params['selectedSupermarket'] = {
634 entityId: entityId,
635 entityName: entityName,
636 entityLabel: entityLabel,
637 };
638 params['targetEntityParamName'] = 'selectedSupermarket';
639 params['selectedDevice'] = null;
640
641 widgetContext.stateController.openState('svgmap', params);
642 {{/code}}
643
644 [[image:1730710990334-601.png||height="772" width="1433"]]
645
646 * (((
647 In this demo, exclusive map icons were set as follows:
648 )))
649
650 {{code language="none"}}
651 var res = {
652 url: images[0],
653 size: 66
654 };
655 return res;
656 {{/code}}
657
658 [[image:1730710395303-672.png||height="771" width="1438"]]
659
660 ===== 4.1.2.3.1 Asset List: =====
661
662 **Data:**
663
664 [[image:1730710693066-349.png||height="772" width="1439"]]
665
666 Actions:The Assets List interface has an action, which is the same as the Supermarket_details in the Map. You can jump to the second level entity interface to view the details of the selected location based on its location
667
668 [[image:1730712335338-750.png||height="751" width="1423"]]
669
670 [[image:1730712473941-913.png||height="781" width="1422"]]
671
672 All Alarms:
673
674 [[image:1730712539209-554.png||height="764" width="1424"]]
675
676 == 4.2 Alarm configuration details ==
677
678 === 4.2.1 High temperature ===
679
680 Creat:
681
682 [[image:1730862483514-101.png||height="750" width="1407"]]
683
684 Clear:
685
686 [[image:1730862584519-902.png||height="758" width="1404"]]
687
688 === 4.2.2 Low Temperature ===
689
690 Creat:
691
692 [[image:1730863708259-750.png||height="752" width="1403"]]
693
694 Clear:
695
696 [[image:1730863750414-979.png||height="746" width="1403"]]
697
698 === 4.2.3 High humidity ===
699
700 Creat:
701
702 [[image:1730864045747-876.png||height="752" width="1396"]]
703
704 Clear:
705
706 [[image:1730864077395-395.png||height="735" width="1393"]]
707
708 === 4.2.4 Low humidity ===
709
710 Creat:
711
712 [[image:1730864117808-484.png||height="741" width="1392"]]
713
714 Clear:
715
716 [[image:1730864159071-895.png||height="745" width="1392"]]
717
718 === 4.2.5 Low voltage ===
719
720 Creat:
721
722 [[image:1730864207037-477.png||height="740" width="1388"]]
723
724 Clear:
725
726 [[image:1730864250506-111.png||height="735" width="1389"]]
727
728 === 4.2.6 Device Disconnected ===
729
730 Creat:
731
732 [[image:1730864293216-991.png||height="739" width="1387"]]
733
734 Clear:
735
736 [[image:1730864331859-740.png||height="735" width="1385"]]
737
738 == 4.3 Rule chain configuration details ==
739
740 [[image:1730864784118-474.png]]
741
742 **Script:**Email configuration for sending device alarm information
743
744 [[image:1730864676542-406.png||height="732" width="1384"]]
745
746 {{code language="none"}}
747 function locatime(timenumber){
748 var date = new Date(timenumber)
749 return date.toLocaleDateString() + ' ' + date.toLocaleTimeString()
750 }
751 var name = msg.name
752 var devicename = msg.originatorName
753 var label = msg.originatorLabel
754 var status = msg.status
755 var detaildata =JSON.parse(msg.details.data)
756 var tempswitch
757
758 if (name != "Device Disconnected") {
759 //detaildata=JSON.parse(msg.details.data)
760 if (detaildata.Temperature_alarm_switch == true) {
761 tempswitch = "open"
762 } else {
763 tempswitch = "close"
764 }
765 var humswitch
766 if (detaildata.Humidity_alarm_switch == true) {
767 humswitch = "open"
768 } else {
769 humswitch = "close"
770 }
771 var batswitch
772 if (detaildata.Voltage_alarm_switch == true) {
773 batswitch = "open"
774 } else {
775 batswitch = "close"
776 }
777 var str2 = "<p>-- Temperature alarm switch status: " +
778 tempswitch + "</p>" +
779 "<p>-- Humidity alarm switch status: " + humswitch +
780 "</p>" +
781 "<p>-- Voltage alarm switch status: " + batswitch
782 }
783
784 if (name == "High Temperature" && status ==
785 "ACTIVE_UNACK") {
786 var emailstr =
787 "<div><p><span style='color: black; font-weight: bold'>" +
788 "Device " + label + " has alarm:</span></p>" +
789 "<p><span style='color: red; font-weight: bold'>-- High Temperature Alarm</span></p>" +
790 "<p>-- Current Temperature : " + detaildata
791 .TempC_SHT + "</p><br>" +
792 "<p>Device Configure:</p>" +
793 "<p>-- Temperature Threshold : min: " + detaildata
794 .Low_temperature_alarm + ", max: " + detaildata
795 .High_temperature_alarm + "</p>" +
796 "<p>-- Humidity Threshold: min: " + detaildata
797 .Low_humidity_alarm + ", max:" + detaildata
798 .High_humidity_alarm + "</p>" +
799 "<p>-- Battery threshold: min: " + detaildata
800 .Low_voltage_alarm + "</p>" + str2 + "</div>"
801 return {
802 msg: {
803 "data": emailstr
804 },
805 metadata: metadata,
806 msgType: msgType
807 };
808 } else if (name == "Low Temperature" && status ==
809 "ACTIVE_UNACK") {
810 var emailstr =
811 "<div><p><span style='color: black; font-weight: bold'>" +
812 "Device " + label + " has alarm:</span></p>" +
813 "<p><span style='color: red; font-weight: bold'>-- Low Temperature Alarm</span></p>" +
814 "<p>-- Current Temperature : " + detaildata
815 .TempC_SHT + "</p><br>" +
816 "<p>Device Configure:</p>" +
817 "<p>-- Temperature Threshold : min: " + detaildata
818 .Low_temperature_alarm + ", max: " + detaildata
819 .High_temperature_alarm + "</p>" +
820 "<p>-- Humidity Threshold: min: " + detaildata
821 .Low_humidity_alarm + ", max:" + detaildata
822 .High_humidity_alarm + "</p>" +
823 "<p>-- Battery threshold: min: " + detaildata
824 .Low_voltage_alarm + "</p>" + str2 + "</div>"
825
826 return {
827 msg: {
828 "data": emailstr
829 },
830 metadata: metadata,
831 msgType: msgType
832 };
833
834 } else if (name == "Device Disconnected" && status ==
835 "ACTIVE_UNACK") {
836 var time1 = locatime(Number(detaildata.lastActivityTime))
837 //var time1 = detaildata.lastActivityTime
838 // var chazhi = parseInt((detaildata.inactivityAlarmTime-detaildata.lastActivityTime)/1000/60)
839 // var emailstr =
840 // "<div><p><span style='color: red; font-weight: bold'>" +
841 // "Device " + label + " has Alarm</span></p><p>Last activity time: "+time1+"</p><p>Last Uplink: 21"+"minutes ago</p></div>"
842
843 var emailstr ="Device " + label + " has Alarm##Last activity time: "+time1+"##Last Uplink: 21minutes ago"
844 var newType = "POST_TELEMETRY_REQUEST"
845 return {
846 msg:emailstr,
847 metadata: metadata,
848 msgType: newType
849 }
850 } else if (name == "High humidity" && status ==
851 "ACTIVE_UNACK") {
852 var emailstr =
853 "<div><p><span style='color: black; font-weight: bold'>" +
854 "Device " + label + " has alarm:</span></p>" +
855 "<p><span style='color: red; font-weight: bold'>-- High Humidity Alarm</span></p>" +
856 "<p>-- Current Temperature : " + detaildata
857 .Hum_SHT + "</p><br>" +
858 "<p>Device Configure:</p>" +
859 "<p>-- Temperature Threshold : min: " + detaildata
860 .Low_temperature_alarm + ", max: " + detaildata
861 .High_temperature_alarm + "</p>" +
862 "<p>-- Humidity Threshold: min: " + detaildata
863 .Low_humidity_alarm + ", max:" + detaildata
864 .High_humidity_alarm + "</p>" +
865 "<p>-- Battery threshold: min: " + detaildata
866 .Low_voltage_alarm + "</p>" + str2 + "</div>"
867
868 return {
869 msg: {
870 "data": emailstr
871 },
872 metadata: metadata,
873 msgType: msgType
874 };
875 } else if (name == "Low humidity" && status ==
876 "ACTIVE_UNACK") {
877 var emailstr =
878 "<div><p><span style='color: black; font-weight: bold'>" +
879 "Device " + label + " has alarm:</span></p>" +
880 "<p><span style='color: red; font-weight: bold'>-- Low Humidity Alarm</span></p>" +
881 "<p>-- Current Temperature : " + detaildata
882 .Hum_SHT + "</p><br>" +
883 "<p>Device Configure:</p>" +
884 "<p>-- Temperature Threshold : min: " + detaildata
885 .Low_temperature_alarm + ", max: " + detaildata
886 .High_temperature_alarm + "</p>" +
887 "<p>-- Humidity Threshold: min: " + detaildata
888 .Low_humidity_alarm + ", max:" + detaildata
889 .High_humidity_alarm + "</p>" +
890 "<p>-- Battery threshold: min: " + detaildata
891 .Low_voltage_alarm + "</p>" + str2 + "</div>"
892
893 return {
894 msg: {
895 "data": emailstr
896 },
897 metadata: metadata,
898 msgType: msgType
899 };
900 } else if (name == "Low voltage" && status ==
901 "ACTIVE_UNACK") {
902 var emailstr =
903 "<div><p><span style='color: black; font-weight: bold'>" +
904 "Device " + label + " has alarm:</span></p>" +
905 "<p><span style='color: red; font-weight: bold'>-- Low Voltage Alarm</span></p>" +
906 "<p>-- Current Temperature : " + detaildata.BatV +
907 "</p><br>" +
908 "<p>Device Configure:</p>" +
909 "<p>-- Temperature Threshold : min: " + detaildata
910 .Low_temperature_alarm + ", max: " + detaildata
911 .High_temperature_alarm + "</p>" +
912 "<p>-- Humidity Threshold: min: " + detaildata
913 .Low_humidity_alarm + ", max:" + detaildata
914 .High_humidity_alarm + "</p>" +
915 "<p>-- Battery threshold: min: " + detaildata
916 .Low_voltage_alarm + "</p>" + str2 + "</div>"
917
918 return {
919 msg: {
920 "data": emailstr
921 },
922 metadata: metadata,
923 msgType: msgType
924 };
925 } else if (name == "High Temperature" && status ==
926 "CLEARED_UNACK") {
927 var emailstr =
928 "<div><p><span style='color: green; font-weight: bold'>Device " +
929 label +
930 " High Temperature Alarm Cleared</span></p>" +
931 "<p>-- Current Temperature : " + detaildata
932 .TempC_SHT + "</p><br>" +
933 "<p>Device Configure:</p>" +
934 "<p>-- Temperature Threshold : min: " + detaildata
935 .Low_temperature_alarm + ", max: " + detaildata
936 .High_temperature_alarm + "</p>" +
937 "<p>-- Humidity Threshold: min: " + detaildata
938 .Low_humidity_alarm + ", max:" + detaildata
939 .High_humidity_alarm + "</p>" +
940 "<p>-- Battery threshold: min: " + detaildata
941 .Low_voltage_alarm + "</p>" + str2 + "</div>"
942
943 return {
944 msg: {
945 "data": emailstr
946 },
947 metadata: metadata,
948 msgType: msgType
949 };
950 } else if (name == "Low Temperature" && status ==
951 "CLEARED_UNACK") {
952 var emailstr =
953 "<div><p><span style='color: green; font-weight: bold'>Device " +
954 label +
955 " Low Temperature Alarm Cleared</span></p>" +
956 "<p>-- Current Temperature : " + detaildata
957 .TempC_SHT + "</p><br>" +
958 "<p>Device Configure:</p>" +
959 "<p>-- Temperature Threshold : min: " + detaildata
960 .Low_temperature_alarm + ", max: " + detaildata
961 .High_temperature_alarm + "</p>" +
962 "<p>-- Humidity Threshold: min: " + detaildata
963 .Low_humidity_alarm + ", max:" + detaildata
964 .High_humidity_alarm + "</p>" +
965 "<p>-- Battery threshold: min: " + detaildata
966 .Low_voltage_alarm + "</p>" + str2 + "</div>"
967
968 return {
969 msg: {
970 "data": emailstr
971 },
972 metadata: metadata,
973 msgType: msgType
974 };
975 } else if (name == "High humidity" && status ==
976 "CLEARED_UNACK") {
977 var emailstr =
978 "<div><p><span style='color: green; font-weight: bold'>Device " +
979 label + " High Humidity Alarm Cleared</span></p>" +
980 "<p>-- Current Temperature : " + detaildata
981 .Hum_SHT + "</p><br>" +
982 "<p>Device Configure:</p>" +
983 "<p>-- Temperature Threshold : min: " + detaildata
984 .Low_temperature_alarm + ", max: " + detaildata
985 .High_temperature_alarm + "</p>" +
986 "<p>-- Humidity Threshold: min: " + detaildata
987 .Low_humidity_alarm + ", max:" + detaildata
988 .High_humidity_alarm + "</p>" +
989 "<p>-- Battery threshold: min: " + detaildata
990 .Low_voltage_alarm + "</p>" + str2 + "</div>"
991
992 return {
993 msg: {
994 "data": emailstr
995 },
996 metadata: metadata,
997 msgType: msgType
998 };
999 } else if (name == "Low humidity" && status ==
1000 "CLEARED_UNACK") {
1001 var emailstr =
1002 "<div><p><span style='color: green; font-weight: bold'>Device " +
1003 label + " Low Humidity Alarm Cleared</span></p>" +
1004 "<p>-- Current Temperature : " + detaildata
1005 .Hum_SHT + "</p><br>" +
1006 "<p>Device Configure:</p>" +
1007 "<p>-- Temperature Threshold : min: " + detaildata
1008 .Low_temperature_alarm + ", max: " + detaildata
1009 .High_temperature_alarm + "</p>" +
1010 "<p>-- Humidity Threshold: min: " + detaildata
1011 .Low_humidity_alarm + ", max:" + detaildata
1012 .High_humidity_alarm + "</p>" +
1013 "<p>-- Battery threshold: min: " + detaildata
1014 .Low_voltage_alarm + "</p>" + str2 + "</div>"
1015 return {
1016 msg: {
1017 "data": emailstr
1018 },
1019 metadata: metadata,
1020 msgType: msgType
1021 };
1022 } else if (name == "Low voltage" && status ==
1023 "CLEARED_UNACK") {
1024
1025 var emailstr =
1026 "<div><p><span style='color: green; font-weight: bold'>Device " +
1027 label + " Low Voltage Alarm Cleared</span></p>" +
1028 "<p>-- Current Temperature : " + detaildata.BatV +
1029 "</p><br><br>" +
1030 "<p>Device Configure:</p>" +
1031 "<p>-- Temperature Threshold : min: " + detaildata
1032 .Low_temperature_alarm + ", max: " + detaildata
1033 .High_temperature_alarm + "</p>" +
1034 "<p>-- Humidity Threshold: min: " + detaildata
1035 .Low_humidity_alarm + ", max:" + detaildata
1036 .High_humidity_alarm + "</p>" +
1037 "<p>-- Battery threshold: min: " + detaildata
1038 .Low_voltage_alarm + "</p>" + str2 + "</div>"
1039
1040 return {
1041 msg: {
1042 "data": emailstr
1043 },
1044 metadata: metadata,
1045 msgType: msgType
1046 };
1047 } else if (name == "Device Disconnected" && status ==
1048 "CLEARED_UNACK") {
1049 var time1 = locatime(Number(detaildata.lastActivityTime))
1050 //var time1 = detaildata.lastActivityTime
1051 // var chazhi = parseInt((detaildata.inactivityAlarmTime-detaildata.lastActivityTime)/1000/60)
1052 // var emailstr =
1053 // "<div><p><span style='color: green; font-weight: bold'>" +
1054 // "Device " + label + " has Alarm Cleared</span></p><p>Last activity time: "+time1+"</p></div>"
1055 var emailstr ="Device " + label + " has Alarm Cleared##Last activity time: "+time1
1056 var newType = "POST_TELEMETRY_REQUEST"
1057 return {
1058 msg: emailstr,
1059 metadata: metadata,
1060 msgType: newType
1061 }
1062 }
1063 {{/code}}
1064
1065 (% class="wikigeneratedid" %)
1066 **Generate Report:**
1067
1068 (% class="wikigeneratedid" %)
1069 [[image:1730865053380-293.png]]
1070
1071 = 5.other =
1072
1073 * If you want to create a similar dashboard, after understanding the case, you can download and import the dashboard, device profiles, rule chains, etc. of the case on GitHub, and make modifications based on them.
1074 * GitHub address:[[https:~~/~~/github.com/ThingsEye-io/te-platform/tree/main/case/Dragino%20Office%20%26%20Factory>>https://github.com/ThingsEye-io/te-platform/tree/main/case/Dragino%20Office%20%26%20Factory]]