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, 52 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
- 屏幕截图 2024-11-04 135045.png
Details
- Page properties
-
- Content
-
... ... @@ -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]]60 +[[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]]85 +[[image:屏幕截图 2024-11-04 135045.png]] 86 86 87 87 = 4.configuration details = 88 88 ... ... @@ -90,17 +90,988 @@ 90 90 91 91 == 4.1 Dashboard configuration details == 92 92 93 -1 、Configurethe interface of the third layerDavies.93 +=== 4.1.1.Data source (Entity aliases) === 94 94 95 +detail:Obtain data based on dashboard status 95 95 96 - 2、Configurethenterfaceof the secondlayer asset97 +[[image:1730709424998-915.png||height="729" width="1436"]] 97 97 99 +Alarm:Obtain alarm information 98 98 99 - 3、Configurethefirstlayer menuinterface101 +[[image:1730709479828-595.png||height="696" width="1435"]] 100 100 103 +Dragino&GXHL,Ltd:Obtain data through asset types 101 101 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" %) 258 +[[image:1730770875793-351.png]] 259 + 260 +(% class="wikigeneratedid" %) 261 +**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 262 + 263 +{{code language="none"}} 264 +var entitySubType; 265 +var $injector = widgetContext.$scope.$injector; 266 +$injector.get(widgetContext.servicesMap.get('entityService')).getEntity(entityId.entityType, entityId.id) 267 + .subscribe(function(data) { 268 + entitySubType = data.type; 269 + console.log(entitySubType) 270 + if (entitySubType == 'gateway') { 271 + openDashboardStates('gateway_detail'); 272 + } else if (entitySubType == 'gxhl01') { 273 + openDashboardStates('detail'); 274 + } 275 + else if(entitySubType == 'AQS01-dragino-office'){ 276 + openDashboardStates("aqs01_detail") 277 + } 278 + else if (entitySubType == 'LDS12') { 279 + openDashboardStates('lds12_detail'); 280 + } 281 + else if (entitySubType == 'LDS02') { 282 + openDashboardStates('lds02_detail'); 283 + } 284 + else if (entitySubType == 'SE01') { 285 + openDashboardStates('se01_detail'); 286 + } 287 + else if (entitySubType == 'PB01') { 288 + openDashboardStates('pb01_detail'); 289 + } 290 + else if (entitySubType == 'LWL02') { 291 + openDashboardStates('lwl02_detail'); 292 + } 293 + else if (entitySubType == 'LPS8N') { 294 + openDashboardStates('lps8n_detail'); 295 + } 296 + else if (entitySubType == 'LHT65N') { 297 + openDashboardStates('lht65n_detail'); 298 + } 299 + else if (entitySubType == 'S31b') { 300 + openDashboardStates('s31b_detail'); 301 + } 302 + }); 303 + 304 +function openDashboardStates(statedId) { 305 + var stateParams = widgetContext.stateController.getStateParams(); 306 + var params = { 307 + entityId: entityId, 308 + entityName: entityName 309 + }; 310 + 311 + if (stateParams.city) { 312 + params.city = stateParams.city; 313 + } 314 + 315 + widgetContext.stateController.openState(statedId, params, false); 316 +} 317 + 318 +{{/code}} 319 + 320 +[[image:1730771103096-522.png]] 321 + 322 +===== 4.1.2.2.2 Device List ===== 323 + 324 +(% class="wikigeneratedid" id="HDataFF1A" %) 325 +**Data:** 326 + 327 +[[image:1730771199343-553.png]] 328 + 329 +**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: 330 + 331 +[[image:1730771228766-212.png]] 332 + 333 +(% class="wikigeneratedid" id="HEditdeviceFF1A" %) 334 +Edit device:Implementation function: Device editing 335 + 336 +[[image:1730771256045-238.png]] 337 + 338 +{{code language="none"}} 339 +let $injector = widgetContext.$scope.$injector; 340 +let customDialog = $injector.get(widgetContext.servicesMap.get('customDialog')); 341 +let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService')); 342 +let attributeService = $injector.get(widgetContext.servicesMap.get('attributeService')); 343 + 344 +openEditDeviceDialog(); 345 + 346 +function openEditDeviceDialog() { 347 + customDialog.customDialog(htmlTemplate, EditDeviceDialogController).subscribe(); 348 +} 349 + 350 +function EditDeviceDialogController(instance) { 351 + let vm = instance; 352 + 353 + vm.device = null; 354 + vm.attributes = {}; 355 + 356 + vm.editDeviceFormGroup = vm.fb.group({ 357 + deviceName: ['', [vm.validators.required]], 358 + deviceType: ['', [vm.validators.required]], 359 + deviceLabel: [''], 360 + attributes: vm.fb.group({ 361 + latitude: [null], 362 + longitude: [null] 363 + }) 364 + }); 365 + 366 + vm.cancel = function() { 367 + vm.dialogRef.close(null); 368 + }; 369 + 370 + vm.save = function() { 371 + vm.editDeviceFormGroup.markAsPristine(); 372 + if (vm.editDeviceFormGroup.get('deviceType').value !== vm.device.type) { 373 + delete vm.device.deviceProfileId; 374 + } 375 + vm.device.name = vm.editDeviceFormGroup.get('deviceName').value, 376 + vm.device.type = vm.editDeviceFormGroup.get('deviceType').value, 377 + vm.device.label = vm.editDeviceFormGroup.get('deviceLabel').value 378 + deviceService.saveDevice(vm.device).subscribe( 379 + function () { 380 + saveAttributes().subscribe( 381 + function () { 382 + widgetContext.updateAliases(); 383 + vm.dialogRef.close(null); 384 + } 385 + ); 386 + } 387 + ); 388 + }; 389 + 390 + getEntityInfo(); 391 + 392 + function getEntityInfo() { 393 + deviceService.getDevice(entityId.id).subscribe( 394 + function (device) { 395 + attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE', 396 + ['latitude', 'longitude']).subscribe( 397 + function (attributes) { 398 + for (let i = 0; i < attributes.length; i++) { 399 + vm.attributes[attributes[i].key] = attributes[i].value; 400 + } 401 + vm.device = device; 402 + vm.editDeviceFormGroup.patchValue( 403 + { 404 + deviceName: vm.device.name, 405 + deviceType: vm.device.type, 406 + deviceLabel: vm.device.label, 407 + attributes: { 408 + latitude: vm.attributes.latitude, 409 + longitude: vm.attributes.longitude 410 + } 411 + }, {emitEvent: false} 412 + ); 413 + } 414 + ); 415 + } 416 + ); 417 + } 418 + 419 + function saveAttributes() { 420 + let attributes = vm.editDeviceFormGroup.get('attributes').value; 421 + let attributesArray = []; 422 + for (let key in attributes) { 423 + attributesArray.push({key: key, value: attributes[key]}); 424 + } 425 + if (attributesArray.length > 0) { 426 + return attributeService.saveEntityAttributes(entityId, 'SERVER_SCOPE', attributesArray); 427 + } else { 428 + return widgetContext.rxjs.of([]); 429 + } 430 + } 431 +} 432 +{{/code}} 433 + 434 +(% class="wikigeneratedid" id="H" %) 435 +Delete device:Implementation function: Device deletion 436 + 437 +[[image:1730771318657-502.png]] 438 + 439 +{{code language="none"}} 440 +let $injector = widgetContext.$scope.$injector; 441 +let dialogs = $injector.get(widgetContext.servicesMap.get('dialogs')); 442 +let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService')); 443 + 444 +openDeleteDeviceDialog(); 445 + 446 +function openDeleteDeviceDialog() { 447 + let title = "Are you sure you want to delete the device " + entityName + "?"; 448 + let content = "Be careful, after the confirmation, the device and all related data will become unrecoverable!"; 449 + dialogs.confirm(title, content, 'Cancel', 'Delete').subscribe( 450 + function (result) { 451 + if (result) { 452 + deleteDevice(); 453 + } 454 + } 455 + ); 456 +} 457 + 458 +function deleteDevice() { 459 + deviceService.deleteDevice(entityId.id).subscribe( 460 + function () { 461 + widgetContext.updateAliases(); 462 + } 463 + ); 464 +} 465 + 466 +{{/code}} 467 + 468 +jump:Implementation function: Jump to the device details page 469 + 470 +[[image:1730771386258-676.png]] 471 + 472 +{{code language="none"}} 473 +console.log(entityName) 474 +var entitySubType; 475 +var $injector = widgetContext.$scope.$injector; 476 +//console.log($injector) 477 +$injector.get(widgetContext.servicesMap.get('entityService')).getEntity(entityId.entityType, entityId.id) 478 + .subscribe(function(data) { 479 + console.log(data) 480 + entitySubType = data.type; 481 + console.log(entitySubType) 482 + if (entitySubType == 'AQS01-dragino-office') { 483 + openDashboardStates('aqs01_detail'); 484 + }else if (entitySubType == 'gateway') { 485 + openDashboardStates('gateway_detail'); 486 + } else if (entitySubType == 'gxhl01') { 487 + openDashboardStates('detail'); 488 + 489 + } else if (entitySubType == 'tank-type1') { 490 + openDashboardStates('test1'); 491 + } 492 + else if (entitySubType == 'LDS12') { 493 + openDashboardStates('lds12_detail'); 494 + } 495 + else if (entitySubType == 'LDS02') { 496 + openDashboardStates('lds02_detail'); 497 + } 498 + else if (entitySubType == 'SE01') { 499 + openDashboardStates('se01_detail'); 500 + } 501 + else if (entitySubType == 'PB01') { 502 + openDashboardStates('pb01_detail'); 503 + } 504 + else if (entitySubType == 'LWL02') { 505 + openDashboardStates('lwl02_detail'); 506 + } 507 + else if (entitySubType == 'LPS8N') { 508 + openDashboardStates('lps8n_detail'); 509 + } 510 + else if (entitySubType == 'LHT65N') { 511 + openDashboardStates('lht65n_detail'); 512 + } 513 + else if (entitySubType == 'S31b') { 514 + openDashboardStates('s31b_detail'); 515 + } 516 + }); 517 + 518 +function openDashboardStates(statedId) { 519 + var stateParams = widgetContext.stateController.getStateParams(); 520 + //console.log(stateParams) 521 + var params = { 522 + entityId: entityId, 523 + entityName: entityName 524 + }; 525 + widgetContext.stateController.updateState(statedId, params, false); 526 +} 527 +{{/code}} 528 + 529 +(% class="wikigeneratedid" id="H-1" %) 530 +Add device:Implementation function: Add device 531 + 532 +[[image:1730771441589-122.png]] 533 + 534 +{{code language="none"}} 535 +let $injector = widgetContext.$scope.$injector; 536 +let customDialog = $injector.get(widgetContext.servicesMap.get('customDialog')); 537 +let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService')); 538 +let attributeService = $injector.get(widgetContext.servicesMap.get('attributeService')); 539 + 540 +openAddDeviceDialog(); 541 + 542 +function openAddDeviceDialog() { 543 + customDialog.customDialog(htmlTemplate, AddDeviceDialogController).subscribe(); 544 +} 545 + 546 +function AddDeviceDialogController(instance) { 547 + let vm = instance; 548 + 549 + vm.addDeviceFormGroup = vm.fb.group({ 550 + deviceName: ['', [vm.validators.required]], 551 + deviceType: ['', [vm.validators.required]], 552 + deviceLabel: [''], 553 + attributes: vm.fb.group({ 554 + latitude: [null], 555 + longitude: [null] 556 + }) 557 + }); 558 + 559 + vm.cancel = function() { 560 + vm.dialogRef.close(null); 561 + }; 562 + 563 + vm.save = function() { 564 + vm.addDeviceFormGroup.markAsPristine(); 565 + let device = { 566 + name: vm.addDeviceFormGroup.get('deviceName').value, 567 + type: vm.addDeviceFormGroup.get('deviceType').value, 568 + label: vm.addDeviceFormGroup.get('deviceLabel').value 569 + }; 570 + deviceService.saveDevice(device).subscribe( 571 + function (device) { 572 + saveAttributes(device.id).subscribe( 573 + function () { 574 + widgetContext.updateAliases(); 575 + vm.dialogRef.close(null); 576 + } 577 + ); 578 + } 579 + ); 580 + }; 581 + 582 + function saveAttributes(entityId) { 583 + let attributes = vm.addDeviceFormGroup.get('attributes').value; 584 + let attributesArray = []; 585 + for (let key in attributes) { 586 + attributesArray.push({key: key, value: attributes[key]}); 587 + } 588 + if (attributesArray.length > 0) { 589 + return attributeService.saveEntityAttributes(entityId, "SERVER_SCOPE", attributesArray); 590 + } else { 591 + return widgetContext.rxjs.of([]); 592 + } 593 + } 594 +} 595 +{{/code}} 596 + 597 +==== ==== 598 + 599 +===== **4.1.2.2.3 Asset Alarm:** ===== 600 + 601 +**Data:** 602 + 603 +[[image:1730771504586-433.png]] 604 + 605 +==== 4.1.2.3、Configure the first layer menu interface ==== 606 + 607 +===== 4.1.2.3.1 **Map:** ===== 608 + 609 +**Data:** 610 + 611 +[[image:1730710271230-716.png||height="729" width="1427"]] 612 + 613 +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 614 + 615 +[[image:1730710850458-781.png||height="770" width="1429"]] 616 + 617 +Select supermarket:Implementation function: Refresh the side page 618 + 619 +{{code language="none"}} 620 +var params = widgetContext.stateController.getStateParams(); 621 +var selectedSupermarket = params['selectedSupermarket']; 622 +if (selectedSupermarket && selectedSupermarket.entityId.id === entityId.id) { 623 + params['selectedSupermarket'] = null; 624 +} else { 625 + params['selectedSupermarket'] = { entityId: entityId, entityName: entityName, entityLabel: entityLabel }; 626 +} 627 +widgetContext.stateController.updateState(null, params); 628 +{{/code}} 629 + 630 +[[image:1730710875401-848.png||height="767" width="1429"]] 631 + 632 +Supermarket_detail:Implementation function: Jump to the asset details page 633 + 634 +{{code language="none"}} 635 +var params = JSON.parse(JSON.stringify(widgetContext.stateController.getStateParams())); 636 +params['selectedSupermarket'] = { 637 + entityId: entityId, 638 + entityName: entityName, 639 + entityLabel: entityLabel, 640 +}; 641 +params['targetEntityParamName'] = 'selectedSupermarket'; 642 +params['selectedDevice'] = null; 643 + 644 +widgetContext.stateController.openState('svgmap', params); 645 +{{/code}} 646 + 647 +[[image:1730710990334-601.png||height="772" width="1433"]] 648 + 649 +* ((( 650 +In this demo, exclusive map icons were set as follows: 651 +))) 652 + 653 +{{code language="none"}} 654 +var res = { 655 + url: images[0], 656 + size: 66 657 +}; 658 +return res; 659 +{{/code}} 660 + 661 +[[image:1730710395303-672.png||height="771" width="1438"]] 662 + 663 +===== 4.1.2.3.1 Asset List: ===== 664 + 665 +**Data:** 666 + 667 +[[image:1730710693066-349.png||height="772" width="1439"]] 668 + 669 +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 670 + 671 +[[image:1730712335338-750.png||height="751" width="1423"]] 672 + 673 +[[image:1730712473941-913.png||height="781" width="1422"]] 674 + 675 +All Alarms: 676 + 677 +[[image:1730712539209-554.png||height="764" width="1424"]] 678 + 102 102 == 4.2 Alarm configuration details == 103 103 681 +=== 4.2.1 High temperature === 682 + 683 +Creat: 684 + 685 +[[image:1730862483514-101.png||height="750" width="1407"]] 686 + 687 +Clear: 688 + 689 +[[image:1730862584519-902.png||height="758" width="1404"]] 690 + 691 +=== 4.2.2 Low Temperature === 692 + 693 +Creat: 694 + 695 +[[image:1730863708259-750.png||height="752" width="1403"]] 696 + 697 +Clear: 698 + 699 +[[image:1730863750414-979.png||height="746" width="1403"]] 700 + 701 +=== 4.2.3 High humidity === 702 + 703 +Creat: 704 + 705 +[[image:1730864045747-876.png||height="752" width="1396"]] 706 + 707 +Clear: 708 + 709 +[[image:1730864077395-395.png||height="735" width="1393"]] 710 + 711 +=== 4.2.4 Low humidity === 712 + 713 +Creat: 714 + 715 +[[image:1730864117808-484.png||height="741" width="1392"]] 716 + 717 +Clear: 718 + 719 +[[image:1730864159071-895.png||height="745" width="1392"]] 720 + 721 +=== 4.2.5 Low voltage === 722 + 723 +Creat: 724 + 725 +[[image:1730864207037-477.png||height="740" width="1388"]] 726 + 727 +Clear: 728 + 729 +[[image:1730864250506-111.png||height="735" width="1389"]] 730 + 731 +=== 4.2.6 Device Disconnected === 732 + 733 +Creat: 734 + 735 +[[image:1730864293216-991.png||height="739" width="1387"]] 736 + 737 +Clear: 738 + 739 +[[image:1730864331859-740.png||height="735" width="1385"]] 740 + 104 104 == 4.3 Rule chain configuration details == 105 105 106 -= 5. = 743 +[[image:1730864784118-474.png]] 744 + 745 +**Script:**Email configuration for sending device alarm information 746 + 747 +[[image:1730864676542-406.png||height="732" width="1384"]] 748 + 749 +{{code language="none"}} 750 +function locatime(timenumber){ 751 + var date = new Date(timenumber) 752 + return date.toLocaleDateString() + ' ' + date.toLocaleTimeString() 753 +} 754 +var name = msg.name 755 +var devicename = msg.originatorName 756 +var label = msg.originatorLabel 757 +var status = msg.status 758 +var detaildata =JSON.parse(msg.details.data) 759 +var tempswitch 760 + 761 +if (name != "Device Disconnected") { 762 + //detaildata=JSON.parse(msg.details.data) 763 + if (detaildata.Temperature_alarm_switch == true) { 764 + tempswitch = "open" 765 + } else { 766 + tempswitch = "close" 767 + } 768 + var humswitch 769 + if (detaildata.Humidity_alarm_switch == true) { 770 + humswitch = "open" 771 + } else { 772 + humswitch = "close" 773 + } 774 + var batswitch 775 + if (detaildata.Voltage_alarm_switch == true) { 776 + batswitch = "open" 777 + } else { 778 + batswitch = "close" 779 + } 780 + var str2 = "<p>-- Temperature alarm switch status: " + 781 + tempswitch + "</p>" + 782 + "<p>-- Humidity alarm switch status: " + humswitch + 783 + "</p>" + 784 + "<p>-- Voltage alarm switch status: " + batswitch 785 +} 786 + 787 +if (name == "High Temperature" && status == 788 + "ACTIVE_UNACK") { 789 + var emailstr = 790 + "<div><p><span style='color: black; font-weight: bold'>" + 791 + "Device " + label + " has alarm:</span></p>" + 792 + "<p><span style='color: red; font-weight: bold'>-- High Temperature Alarm</span></p>" + 793 + "<p>-- Current Temperature : " + detaildata 794 + .TempC_SHT + "</p><br>" + 795 + "<p>Device Configure:</p>" + 796 + "<p>-- Temperature Threshold : min: " + detaildata 797 + .Low_temperature_alarm + ", max: " + detaildata 798 + .High_temperature_alarm + "</p>" + 799 + "<p>-- Humidity Threshold: min: " + detaildata 800 + .Low_humidity_alarm + ", max:" + detaildata 801 + .High_humidity_alarm + "</p>" + 802 + "<p>-- Battery threshold: min: " + detaildata 803 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 804 + return { 805 + msg: { 806 + "data": emailstr 807 + }, 808 + metadata: metadata, 809 + msgType: msgType 810 + }; 811 +} else if (name == "Low Temperature" && status == 812 + "ACTIVE_UNACK") { 813 + var emailstr = 814 + "<div><p><span style='color: black; font-weight: bold'>" + 815 + "Device " + label + " has alarm:</span></p>" + 816 + "<p><span style='color: red; font-weight: bold'>-- Low Temperature Alarm</span></p>" + 817 + "<p>-- Current Temperature : " + detaildata 818 + .TempC_SHT + "</p><br>" + 819 + "<p>Device Configure:</p>" + 820 + "<p>-- Temperature Threshold : min: " + detaildata 821 + .Low_temperature_alarm + ", max: " + detaildata 822 + .High_temperature_alarm + "</p>" + 823 + "<p>-- Humidity Threshold: min: " + detaildata 824 + .Low_humidity_alarm + ", max:" + detaildata 825 + .High_humidity_alarm + "</p>" + 826 + "<p>-- Battery threshold: min: " + detaildata 827 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 828 + 829 + return { 830 + msg: { 831 + "data": emailstr 832 + }, 833 + metadata: metadata, 834 + msgType: msgType 835 + }; 836 + 837 +} else if (name == "Device Disconnected" && status == 838 + "ACTIVE_UNACK") { 839 + var time1 = locatime(Number(detaildata.lastActivityTime)) 840 + //var time1 = detaildata.lastActivityTime 841 + // var chazhi = parseInt((detaildata.inactivityAlarmTime-detaildata.lastActivityTime)/1000/60) 842 + // var emailstr = 843 + // "<div><p><span style='color: red; font-weight: bold'>" + 844 + // "Device " + label + " has Alarm</span></p><p>Last activity time: "+time1+"</p><p>Last Uplink: 21"+"minutes ago</p></div>" 845 + 846 + var emailstr ="Device " + label + " has Alarm##Last activity time: "+time1+"##Last Uplink: 21minutes ago" 847 + var newType = "POST_TELEMETRY_REQUEST" 848 + return { 849 + msg:emailstr, 850 + metadata: metadata, 851 + msgType: newType 852 + } 853 +} else if (name == "High humidity" && status == 854 + "ACTIVE_UNACK") { 855 + var emailstr = 856 + "<div><p><span style='color: black; font-weight: bold'>" + 857 + "Device " + label + " has alarm:</span></p>" + 858 + "<p><span style='color: red; font-weight: bold'>-- High Humidity Alarm</span></p>" + 859 + "<p>-- Current Temperature : " + detaildata 860 + .Hum_SHT + "</p><br>" + 861 + "<p>Device Configure:</p>" + 862 + "<p>-- Temperature Threshold : min: " + detaildata 863 + .Low_temperature_alarm + ", max: " + detaildata 864 + .High_temperature_alarm + "</p>" + 865 + "<p>-- Humidity Threshold: min: " + detaildata 866 + .Low_humidity_alarm + ", max:" + detaildata 867 + .High_humidity_alarm + "</p>" + 868 + "<p>-- Battery threshold: min: " + detaildata 869 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 870 + 871 + return { 872 + msg: { 873 + "data": emailstr 874 + }, 875 + metadata: metadata, 876 + msgType: msgType 877 + }; 878 +} else if (name == "Low humidity" && status == 879 + "ACTIVE_UNACK") { 880 + var emailstr = 881 + "<div><p><span style='color: black; font-weight: bold'>" + 882 + "Device " + label + " has alarm:</span></p>" + 883 + "<p><span style='color: red; font-weight: bold'>-- Low Humidity Alarm</span></p>" + 884 + "<p>-- Current Temperature : " + detaildata 885 + .Hum_SHT + "</p><br>" + 886 + "<p>Device Configure:</p>" + 887 + "<p>-- Temperature Threshold : min: " + detaildata 888 + .Low_temperature_alarm + ", max: " + detaildata 889 + .High_temperature_alarm + "</p>" + 890 + "<p>-- Humidity Threshold: min: " + detaildata 891 + .Low_humidity_alarm + ", max:" + detaildata 892 + .High_humidity_alarm + "</p>" + 893 + "<p>-- Battery threshold: min: " + detaildata 894 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 895 + 896 + return { 897 + msg: { 898 + "data": emailstr 899 + }, 900 + metadata: metadata, 901 + msgType: msgType 902 + }; 903 +} else if (name == "Low voltage" && status == 904 + "ACTIVE_UNACK") { 905 + var emailstr = 906 + "<div><p><span style='color: black; font-weight: bold'>" + 907 + "Device " + label + " has alarm:</span></p>" + 908 + "<p><span style='color: red; font-weight: bold'>-- Low Voltage Alarm</span></p>" + 909 + "<p>-- Current Temperature : " + detaildata.BatV + 910 + "</p><br>" + 911 + "<p>Device Configure:</p>" + 912 + "<p>-- Temperature Threshold : min: " + detaildata 913 + .Low_temperature_alarm + ", max: " + detaildata 914 + .High_temperature_alarm + "</p>" + 915 + "<p>-- Humidity Threshold: min: " + detaildata 916 + .Low_humidity_alarm + ", max:" + detaildata 917 + .High_humidity_alarm + "</p>" + 918 + "<p>-- Battery threshold: min: " + detaildata 919 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 920 + 921 + return { 922 + msg: { 923 + "data": emailstr 924 + }, 925 + metadata: metadata, 926 + msgType: msgType 927 + }; 928 +} else if (name == "High Temperature" && status == 929 + "CLEARED_UNACK") { 930 + var emailstr = 931 + "<div><p><span style='color: green; font-weight: bold'>Device " + 932 + label + 933 + " High Temperature Alarm Cleared</span></p>" + 934 + "<p>-- Current Temperature : " + detaildata 935 + .TempC_SHT + "</p><br>" + 936 + "<p>Device Configure:</p>" + 937 + "<p>-- Temperature Threshold : min: " + detaildata 938 + .Low_temperature_alarm + ", max: " + detaildata 939 + .High_temperature_alarm + "</p>" + 940 + "<p>-- Humidity Threshold: min: " + detaildata 941 + .Low_humidity_alarm + ", max:" + detaildata 942 + .High_humidity_alarm + "</p>" + 943 + "<p>-- Battery threshold: min: " + detaildata 944 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 945 + 946 + return { 947 + msg: { 948 + "data": emailstr 949 + }, 950 + metadata: metadata, 951 + msgType: msgType 952 + }; 953 +} else if (name == "Low Temperature" && status == 954 + "CLEARED_UNACK") { 955 + var emailstr = 956 + "<div><p><span style='color: green; font-weight: bold'>Device " + 957 + label + 958 + " Low Temperature Alarm Cleared</span></p>" + 959 + "<p>-- Current Temperature : " + detaildata 960 + .TempC_SHT + "</p><br>" + 961 + "<p>Device Configure:</p>" + 962 + "<p>-- Temperature Threshold : min: " + detaildata 963 + .Low_temperature_alarm + ", max: " + detaildata 964 + .High_temperature_alarm + "</p>" + 965 + "<p>-- Humidity Threshold: min: " + detaildata 966 + .Low_humidity_alarm + ", max:" + detaildata 967 + .High_humidity_alarm + "</p>" + 968 + "<p>-- Battery threshold: min: " + detaildata 969 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 970 + 971 + return { 972 + msg: { 973 + "data": emailstr 974 + }, 975 + metadata: metadata, 976 + msgType: msgType 977 + }; 978 +} else if (name == "High humidity" && status == 979 + "CLEARED_UNACK") { 980 + var emailstr = 981 + "<div><p><span style='color: green; font-weight: bold'>Device " + 982 + label + " High Humidity Alarm Cleared</span></p>" + 983 + "<p>-- Current Temperature : " + detaildata 984 + .Hum_SHT + "</p><br>" + 985 + "<p>Device Configure:</p>" + 986 + "<p>-- Temperature Threshold : min: " + detaildata 987 + .Low_temperature_alarm + ", max: " + detaildata 988 + .High_temperature_alarm + "</p>" + 989 + "<p>-- Humidity Threshold: min: " + detaildata 990 + .Low_humidity_alarm + ", max:" + detaildata 991 + .High_humidity_alarm + "</p>" + 992 + "<p>-- Battery threshold: min: " + detaildata 993 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 994 + 995 + return { 996 + msg: { 997 + "data": emailstr 998 + }, 999 + metadata: metadata, 1000 + msgType: msgType 1001 + }; 1002 +} else if (name == "Low humidity" && status == 1003 + "CLEARED_UNACK") { 1004 + var emailstr = 1005 + "<div><p><span style='color: green; font-weight: bold'>Device " + 1006 + label + " Low Humidity Alarm Cleared</span></p>" + 1007 + "<p>-- Current Temperature : " + detaildata 1008 + .Hum_SHT + "</p><br>" + 1009 + "<p>Device Configure:</p>" + 1010 + "<p>-- Temperature Threshold : min: " + detaildata 1011 + .Low_temperature_alarm + ", max: " + detaildata 1012 + .High_temperature_alarm + "</p>" + 1013 + "<p>-- Humidity Threshold: min: " + detaildata 1014 + .Low_humidity_alarm + ", max:" + detaildata 1015 + .High_humidity_alarm + "</p>" + 1016 + "<p>-- Battery threshold: min: " + detaildata 1017 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 1018 + return { 1019 + msg: { 1020 + "data": emailstr 1021 + }, 1022 + metadata: metadata, 1023 + msgType: msgType 1024 + }; 1025 +} else if (name == "Low voltage" && status == 1026 + "CLEARED_UNACK") { 1027 + 1028 + var emailstr = 1029 + "<div><p><span style='color: green; font-weight: bold'>Device " + 1030 + label + " Low Voltage Alarm Cleared</span></p>" + 1031 + "<p>-- Current Temperature : " + detaildata.BatV + 1032 + "</p><br><br>" + 1033 + "<p>Device Configure:</p>" + 1034 + "<p>-- Temperature Threshold : min: " + detaildata 1035 + .Low_temperature_alarm + ", max: " + detaildata 1036 + .High_temperature_alarm + "</p>" + 1037 + "<p>-- Humidity Threshold: min: " + detaildata 1038 + .Low_humidity_alarm + ", max:" + detaildata 1039 + .High_humidity_alarm + "</p>" + 1040 + "<p>-- Battery threshold: min: " + detaildata 1041 + .Low_voltage_alarm + "</p>" + str2 + "</div>" 1042 + 1043 + return { 1044 + msg: { 1045 + "data": emailstr 1046 + }, 1047 + metadata: metadata, 1048 + msgType: msgType 1049 + }; 1050 +} else if (name == "Device Disconnected" && status == 1051 + "CLEARED_UNACK") { 1052 + var time1 = locatime(Number(detaildata.lastActivityTime)) 1053 + //var time1 = detaildata.lastActivityTime 1054 + // var chazhi = parseInt((detaildata.inactivityAlarmTime-detaildata.lastActivityTime)/1000/60) 1055 + // var emailstr = 1056 + // "<div><p><span style='color: green; font-weight: bold'>" + 1057 + // "Device " + label + " has Alarm Cleared</span></p><p>Last activity time: "+time1+"</p></div>" 1058 + var emailstr ="Device " + label + " has Alarm Cleared##Last activity time: "+time1 1059 + var newType = "POST_TELEMETRY_REQUEST" 1060 + return { 1061 + msg: emailstr, 1062 + metadata: metadata, 1063 + msgType: newType 1064 + } 1065 +} 1066 +{{/code}} 1067 + 1068 +(% class="wikigeneratedid" %) 1069 +**Generate Report:** 1070 + 1071 +(% class="wikigeneratedid" %) 1072 +[[image:1730865053380-293.png]] 1073 + 1074 += 5.other = 1075 + 1076 +* 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. 1077 +* 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
- 屏幕截图 2024-11-04 135045.png
-
- Author
-
... ... @@ -1,0 +1,1 @@ 1 +XWiki.hera - Size
-
... ... @@ -1,0 +1,1 @@ 1 +29.4 KB - Content