Wiki source code of Demo for Smart Office, Factory

Last modified by Hera Guo on 2024/11/11 17:08

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