Changes for page Demo for Smart Office, Factory
Last modified by Hera Guo on 2024/11/11 17:08
Summary
-
Page properties (1 modified, 0 added, 0 removed)
-
Attachments (0 modified, 54 added, 0 removed)
- 1730709382428-730.png
- 1730709409941-536.png
- 1730709424998-915.png
- 1730709442773-502.png
- 1730709461297-207.png
- 1730709479828-595.png
- 1730709511861-439.png
- 1730709527720-418.png
- 1730709542597-321.png
- 1730709555797-383.png
- 1730710271230-716.png
- 1730710395303-672.png
- 1730710693066-349.png
- 1730710850458-781.png
- 1730710875401-848.png
- 1730710949358-671.png
- 1730710990334-601.png
- 1730712335338-750.png
- 1730712473941-913.png
- 1730712539209-554.png
- 1730770392454-317.png
- 1730770636230-829.png
- 1730770875793-351.png
- 1730771103096-522.png
- 1730771199343-553.png
- 1730771228766-212.png
- 1730771256045-238.png
- 1730771318657-502.png
- 1730771386258-676.png
- 1730771441589-122.png
- 1730771504586-433.png
- 1730857191863-514.png
- 1730857537965-184.png
- 1730857750749-240.png
- 1730862483514-101.png
- 1730862584519-902.png
- 1730863708259-750.png
- 1730863750414-979.png
- 1730864045747-876.png
- 1730864077395-395.png
- 1730864117808-484.png
- 1730864159071-895.png
- 1730864207037-477.png
- 1730864250506-111.png
- 1730864293216-991.png
- 1730864331859-740.png
- 1730864460314-611.png
- 1730864617480-221.png
- 1730864676542-406.png
- 1730864784118-474.png
- 1730865053380-293.png
- 1731315784538-942.png
- 1731315965141-491.png
- 屏幕截图 2024-11-04 135045.png
Details
- Page properties
-
- Content
-
... ... @@ -1,4 +1,4 @@ 1 -**Table of Contents:** 1 + **Table of Contents:** 2 2 3 3 {{toc/}} 4 4 ... ... @@ -5,6 +5,9 @@ 5 5 6 6 7 7 8 + 9 + 10 + 8 8 = 1. About this demo = 9 9 10 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. ... ... @@ -57,7 +57,7 @@ 57 57 58 58 **device:**This section displays the specific information collected by the device, and different types of sensors have different display interfaces 59 59 60 -[[image: 1730699212334-960.png]]63 +[[image:屏幕截图 2024-11-04 134645.png]] 61 61 62 62 First floor: 63 63 ... ... @@ -82,7 +82,7 @@ 82 82 83 83 High Temperature、Low Temperature、High humidity、Low humidity、Low voltage、Device Disconnected 84 84 85 -[[image:1 730699566023-958.png]]88 +[[image:屏幕截图 2024-11-04 135045.png]] 86 86 87 87 = 4.configuration details = 88 88 ... ... @@ -90,17 +90,999 @@ 90 90 91 91 == 4.1 Dashboard configuration details == 92 92 93 -1 、Configurethe interface of the third layerDavies.96 +=== 4.1.1.Data source (Entity aliases) === 94 94 98 +detail:Obtain data based on dashboard status 95 95 96 - 2、Configurethenterfaceof the secondlayer asset100 +[[image:1730709424998-915.png||height="729" width="1436"]] 97 97 102 +Alarm:Obtain alarm information 98 98 99 - 3、Configurethefirstlayer menuinterface104 +[[image:1730709479828-595.png||height="696" width="1435"]] 100 100 106 +Dragino&GXHL,Ltd:Obtain data through asset types 101 101 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 + 102 102 == 4.2 Alarm configuration details == 103 103 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 + 104 104 == 4.3 Rule chain configuration details == 105 105 106 -= 5. = 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]]
- 1730709382428-730.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +480.8 KB - Content
- 1730709409941-536.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +451.5 KB - Content
- 1730709424998-915.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +443.4 KB - Content
- 1730709442773-502.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +448.3 KB - Content
- 1730709461297-207.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +458.2 KB - Content
- 1730709479828-595.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +450.7 KB - Content
- 1730709511861-439.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +470.0 KB - Content
- 1730709527720-418.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +475.8 KB - Content
- 1730709542597-321.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +474.8 KB - Content
- 1730709555797-383.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +463.2 KB - Content
- 1730710271230-716.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.5 MB - Content
- 1730710395303-672.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.6 MB - Content
- 1730710693066-349.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +94.4 KB - Content
- 1730710850458-781.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.5 MB - Content
- 1730710875401-848.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.0 MB - Content
- 1730710949358-671.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.0 MB - Content
- 1730710990334-601.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +1.0 MB - Content
- 1730712335338-750.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +77.1 KB - Content
- 1730712473941-913.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +135.9 KB - Content
- 1730712539209-554.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +131.0 KB - Content
- 1730770392454-317.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +195.6 KB - Content
- 1730770636230-829.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +290.6 KB - Content
- 1730770875793-351.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +305.2 KB - Content
- 1730771103096-522.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +197.9 KB - Content
- 1730771199343-553.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +108.5 KB - Content
- 1730771228766-212.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +46.8 KB - Content
- 1730771256045-238.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +69.1 KB - Content
- 1730771318657-502.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +60.4 KB - Content
- 1730771386258-676.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +46.4 KB - Content
- 1730771441589-122.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +57.6 KB - Content
- 1730771504586-433.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +151.2 KB - Content
- 1730857191863-514.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +354.7 KB - Content
- 1730857537965-184.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +455.1 KB - Content
- 1730857750749-240.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +285.9 KB - Content
- 1730862483514-101.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +195.8 KB - Content
- 1730862584519-902.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +191.1 KB - Content
- 1730863708259-750.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +220.1 KB - Content
- 1730863750414-979.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +210.6 KB - Content
- 1730864045747-876.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +208.9 KB - Content
- 1730864077395-395.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +201.4 KB - Content
- 1730864117808-484.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +203.0 KB - Content
- 1730864159071-895.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +226.6 KB - Content
- 1730864207037-477.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +215.3 KB - Content
- 1730864250506-111.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +209.5 KB - Content
- 1730864293216-991.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +138.5 KB - Content
- 1730864331859-740.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +134.4 KB - Content
- 1730864460314-611.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +256.7 KB - Content
- 1730864617480-221.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +260.8 KB - Content
- 1730864676542-406.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +227.7 KB - Content
- 1730864784118-474.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +148.8 KB - Content
- 1730865053380-293.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +46.7 KB - Content
- 1731315784538-942.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +50.2 KB - Content
- 1731315965141-491.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +447.8 KB - Content
- 屏幕截图 2024-11-04 135045.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +29.4 KB - Content