Thread XML Wert auslesen (3 answers)
Opened by Jan0579 at 2016-08-16 10:04

Jan0579
 2016-08-16 10:04
#185263 #185263
User since
2016-08-15
2 Artikel
BenutzerIn
[default_avatar]
Hallo zusammen,

ich habe ein Problem mit einem Perl-Skript, welches mir Werte aus XML-Dokumenten ausliest.

Hier ein Ausschnitt des gegebenen XMLs:

more (2.0kb):

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="ISO-8859-1" ?>
<stateList>
<device name='FK_Schlafzimmer' ise_id='3651' unreach='false' sticky_unreach='false' config_pending='false' >
<channel name='HM-Sec-SCo NEQ0099235:1' ise_id='3680' visible='true' operate='true'>
<datapoint name='BidCos-RF.NEQ0099235:1.STATE' type='STATE' ise_id='3705' value='true' valuetype='2' valueunit='' timestamp='1471165950' operations='5' />
<datapoint name='BidCos-RF.NEQ0099235:1.ERROR' type='ERROR' ise_id='3681' value='0' valuetype='16' valueunit='' timestamp='1471165184' operations='5' />
<datapoint name='BidCos-RF.NEQ0099235:1.LOWBAT' type='LOWBAT' ise_id='3704' value='false' valuetype='2' valueunit='' timestamp='1471165949' operations='5' />
</channel>
</device>
<device name='SA_Waschmaschine' ise_id='3574' unreach='false' sticky_unreach='true' config_pending='false' >
<channel name='HM-ES-PMSw1-Pl LEQ1316672:1' ise_id='3603' visible='true' operate='true'>
<datapoint name='BidCos-RF.LEQ1316672:1.STATE' type='STATE' ise_id='3607' value='true' valuetype='2' valueunit='' timestamp='1471163536' operations='7' />
</channel>
</device>
</stateList>



Hier das verwendete Skript mit den relevanten Auszügen:

more (4.9kb):

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use strict;
use warnings;
use lib "/root/perl5/lib/perl5/";
use POSIX qw/ strftime /;
use LWP::Simple;
use XML::Simple;
use Data::Dumper;
use Getopt::Long;
use Switch;

# define variables
my $path = "C:/test/Sonstiges/XML/";
my $pathyear = $path.strftime("%Y", localtime);
my $pathmonth = $pathyear.'/'.strftime("%Y-%m", localtime);
my $pathday = $pathmonth.'/'.strftime("%Y-%m-%d", localtime);
my $filename = strftime("%Y-%m-%d_%H-%M-%S", localtime)."_statelist.xml";
my $filepath = $pathday.'/'.$filename;
my $host = 'SA_Waschmaschine';
my $XMLdata = '';
my $EXECtype = 'value';
my $datapoint_input = 'POWSTAT';
my $datapoint;
my $warning;
my $critical;
my $return;
my $return_value;
my $return_messure;
my $help_hint;

# mapping datapoint name
switch ($datapoint_input) {
case 'ACTTEMP' { $datapoint = 'ACTUAL_TEMPERATURE' }
case 'SETTEMP' { $datapoint = 'SET_TEMPERATURE' }
case 'HUM' { $datapoint = 'ACTUAL_HUMIDITY' }
case 'LOWBAT' { $datapoint = 'LOWBAT' }
case 'BATSTAT' { $datapoint = 'BATTERY_STATE' }
case 'CFGPEN' { $datapoint = 'CONFIG_PENDING' }
case 'UPDPEN' { $datapoint = 'UPDATE_PENDING' }
case 'DEVBOL' { $datapoint = 'DEVICE_IN_BOOTLOADER' }
case 'UNREACH' { $datapoint = 'UNREACH' }
case 'POWSTAT' { $datapoint = 'STATE' }
case 'WINSTAT' { $datapoint = 'STATE'}
case 'VALSTAT' { $datapoint = 'VALVE_STATE'}
case 'BOOSTAT' { $datapoint = 'BOOST_STATE' }
else {
$help_hint = 'datapoint';
print_help();
}
}

if ($EXECtype eq 'value') {
# check variables
if ($host and $path and $datapoint) {
$return = check_value();
if ($return == 0) {
exit 0;
};
if ($return == 1) {
exit 1;
};
if ($return == 2) {
exit 2;
};
}
else {
print_help();
}
}

sub check_value {
if (($datapoint eq 'STATE') and ($datapoint_input eq 'POWSTAT')) {
$return = check_POWSTAT();
};
return $return;

}

sub check_POWSTAT {
$return_value = get_value();
if ($return_value eq 'false') {
print "power off OK - power state $host | power_state=0";
return 0;
};
if ($return_value eq 'true') {
print "power on WARNING - power state $host | power_state=1";
return 1;
};
if ($return_value eq '-99') {
print "$return_value $datapoint CRITICAL - power state $host - value not found";
return 2;
};
}

sub get_value {
opendir(DIR, "$pathday") || die $!;
my @a=readdir(DIR);
close DIR;
@a = sort @a;
my $last = @a-1;
$filepath = $pathday.'/'.$a[$last];
my $value;
my $opt = XMLin("$filepath", KeyAttr => {device => 'name', datapoint => 'type'});
$return_value = -99;
foreach my $channel (@{$opt->{device}->{$host}->{channel}})
{
$value = $channel->{datapoint}->{$datapoint}->{value};
my $messure = $channel->{datapoint}->{$datapoint}->{valueunit};
if (defined $value)
{
$return_value = $value;
$return_messure = $messure;
};
};
return $return_value;
}



Das Problem ist, wenn im XML unter dem jeweiligen Channel nur ein Datapoint ist. (z.B. bei SA_Waschmaschine) Dann findet das Skript keinen Wert für den Type='STATE'. Wenn mehrere Datapoints unter einem Channel sind, wie bei FK_Schlafzimmer, dann findet das Skript den Type mit zugehörigem Wert.

Das Problem liegt vermutlich beim Aufruf mit foreach im sub_get_Value(), aber ich hab aktuell keine Idee, wie ich das beheben kann.

Vielleicht hat jemand von Euch eine Idee?

Vielen Dank vorab!

Gruss
Jan
Last edited: 2016-08-16 10:28:42 +0200 (CEST)

View full thread XML Wert auslesen