Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
dcdb
dcdb
Commits
53a60288
Commit
53a60288
authored
Aug 29, 2019
by
Michael Ott
Browse files
Add support for Lenovo XCC power readings
parent
5d792aaa
Changes
5
Hide whitespace changes
Inline
Side-by-side
dcdbpusher/Makefile
View file @
53a60288
...
...
@@ -84,7 +84,7 @@ libdcdbplugin_sysfs.$(LIBEXT): sensors/sysfs/SysfsSensorGroup.o sensors/sysfs/Sy
libdcdbplugin_perfevent.$(LIBEXT)
:
sensors/perfevent/PerfSensorGroup.o sensors/perfevent/PerfeventConfigurator.o
$(CXX)
$(LIBFLAGS)$@
-o
$@
$^
-L
$(DCDBDEPLOYPATH)
/lib/
-lboost_log
-lboost_system
libdcdbplugin_ipmi.$(LIBEXT)
:
sensors/ipmi/IPMISensorGroup.o sensors/ipmi/IPMIHost.o sensors/ipmi/IPMIConfigurator.o
libdcdbplugin_ipmi.$(LIBEXT)
:
sensors/ipmi/IPMISensorGroup.o sensors/ipmi/IPMIHost.o sensors/ipmi/IPMIConfigurator.o
sensors/ipmi/LenovoXCC.o
$(CXX)
$(LIBFLAGS)$@
-o
$@
$^
-L
$(DCDBDEPLOYPATH)
/lib/
-lboost_log
-lboost_system
-lboost_regex
-lfreeipmi
libdcdbplugin_pdu.$(LIBEXT)
:
sensors/pdu/PDUSensorGroup.o sensors/pdu/PDUUnit.o sensors/pdu/PDUConfigurator.o
...
...
dcdbpusher/sensors/ipmi/IPMISensorBase.h
View file @
53a60288
...
...
@@ -87,7 +87,8 @@ public:
enum
sensorType
{
undefined
=
0
,
raw
,
sdr
sdr
,
xcc
};
uint16_t
getRecordId
()
const
{
return
_recordId
;
}
...
...
@@ -104,10 +105,12 @@ public:
}
uint8_t
getLsb
()
const
{
return
_lsb
;
}
uint8_t
getMsb
()
const
{
return
_msb
;
}
std
::
string
getType
()
const
{
sensorType
getType
()
const
{
return
_type
;
}
std
::
string
getTypeString
()
const
{
switch
(
_type
)
{
case
raw
:
return
std
::
string
(
"raw"
);
case
sdr
:
return
std
::
string
(
"sdr"
);
case
xcc
:
return
std
::
string
(
"xcc"
);
default:
return
std
::
string
(
"undefined"
);
}
}
...
...
@@ -136,6 +139,8 @@ public:
_type
=
raw
;
}
else
if
(
boost
::
iequals
(
type
,
"sdr"
))
{
_type
=
sdr
;
}
else
if
(
boost
::
iequals
(
type
,
"xcc"
))
{
_type
=
xcc
;
}
else
{
_type
=
undefined
;
}
...
...
@@ -143,7 +148,7 @@ public:
void
printConfig
(
LOG_LEVEL
ll
,
LOGGER
&
lg
,
unsigned
leadingSpaces
=
16
)
{
std
::
string
leading
(
leadingSpaces
,
' '
);
LOG_VAR
(
ll
)
<<
leading
<<
" Type: "
<<
getType
();
LOG_VAR
(
ll
)
<<
leading
<<
" Type: "
<<
getType
String
();
switch
(
_type
)
{
case
raw
:
LOG_VAR
(
ll
)
<<
leading
<<
" Raw Cmd: "
<<
getRawCmdString
();
...
...
@@ -153,11 +158,14 @@ public:
case
sdr
:
LOG_VAR
(
ll
)
<<
leading
<<
" Record Id: "
<<
_recordId
;
break
;
default:
break
;
}
LOG_VAR
(
ll
)
<<
leading
<<
" Factor: "
<<
_factor
;
}
protected:
sensorType
_type
;
uint16_t
_recordId
;
std
::
vector
<
uint8_t
>
_sdrRecord
;
double
_factor
;
...
...
@@ -165,7 +173,6 @@ protected:
std
::
vector
<
uint8_t
>
_rawCmd
;
uint8_t
_lsb
;
uint8_t
_msb
;
sensorType
_type
;
};
#endif
/* SRC_SENSORS_IPMI_IPMISENSORBASE_H_ */
dcdbpusher/sensors/ipmi/IPMISensorGroup.cpp
View file @
53a60288
...
...
@@ -27,6 +27,7 @@
#include
"IPMISensorGroup.h"
#include
"IPMIHost.h"
#include
"LenovoXCC.h"
#include
<iostream>
#include
<exception>
...
...
@@ -100,20 +101,46 @@ void IPMISensorGroup::read() {
for
(
const
auto
&
s
:
_sensors
)
{
try
{
if
(
s
->
getRecordId
()
!=
0
)
{
/* recordId was set */
std
::
vector
<
uint8_t
>
sdrRecord
=
s
->
getSdrRecord
();
if
(
sdrRecord
.
size
()
==
0
)
{
_entity
->
getSdrRecord
(
s
->
getRecordId
(),
sdrRecord
);
s
->
setSdrRecord
(
sdrRecord
);
}
reading
.
value
=
_entity
->
readSensorRecord
(
sdrRecord
);
}
else
{
/* use raw command */
reading
.
value
=
readRaw
(
s
->
getRawCmd
(),
s
->
getLsb
(),
s
->
getMsb
());
}
if
(
s
->
getType
()
==
IPMISensorBase
::
sensorType
::
xcc
)
{
LenovoXCC
xcc
(
_entity
);
if
(
xcc
.
openDatastore
()
==
0
)
{
uint64_t
ts1
,
ts2
;
std
::
vector
<
uint16_t
>
readings
;
if
((
ts1
=
xcc
.
readDatastoreTimestamp
())
>
0
)
{
if
(
xcc
.
readDatastorePower
(
readings
)
==
0
)
{
// Check whether the timestamp changed during readDatastorePower() and re-read if it did
ts2
=
xcc
.
readDatastoreTimestamp
();
if
(
ts2
>
ts1
)
{
xcc
.
readDatastorePower
(
readings
);
ts1
=
ts2
;
}
}
xcc
.
closeDatastore
();
}
ts1
+=
xcc
.
getDrift
();
for
(
unsigned
int
i
=
0
;
i
<
readings
.
size
();
i
++
)
{
reading
.
timestamp
=
ts1
+
MS_TO_NS
(
i
*
10
);
reading
.
value
=
readings
[
i
];
s
->
storeReading
(
reading
,
s
->
getFactor
());
// LOG(debug) << _groupName << "::" << s->getName() << " xcc: " << i << " " << reading.timestamp << " " << reading.value;
}
}
}
else
{
if
(
s
->
getType
()
==
IPMISensorBase
::
sensorType
::
sdr
)
{
std
::
vector
<
uint8_t
>
sdrRecord
=
s
->
getSdrRecord
();
if
(
sdrRecord
.
size
()
==
0
)
{
_entity
->
getSdrRecord
(
s
->
getRecordId
(),
sdrRecord
);
s
->
setSdrRecord
(
sdrRecord
);
}
reading
.
value
=
_entity
->
readSensorRecord
(
sdrRecord
);
}
else
{
reading
.
value
=
readRaw
(
s
->
getRawCmd
(),
s
->
getLsb
(),
s
->
getMsb
());
}
#ifdef DEBUG
LOG
(
debug
)
<<
_groupName
<<
"::"
<<
s
->
getName
()
<<
" raw reading:
\"
"
<<
reading
.
value
<<
"
\"
"
;
LOG
(
debug
)
<<
_groupName
<<
"::"
<<
s
->
getName
()
<<
" raw reading:
\"
"
<<
reading
.
value
<<
"
\"
"
;
#endif
s
->
storeReading
(
reading
,
s
->
getFactor
());
s
->
storeReading
(
reading
,
s
->
getFactor
());
}
}
catch
(
const
std
::
exception
&
e
)
{
LOG
(
error
)
<<
_groupName
<<
"::"
<<
s
->
getName
()
<<
" could not read value: "
<<
e
.
what
();
continue
;
...
...
dcdbpusher/sensors/ipmi/LenovoXCC.cpp
0 → 100644
View file @
53a60288
//
// LenovoXCC.cpp
// dcdb
//
// Created by Ott, Michael on 21.08.19.
// Copyright © 2019 LRZ. All rights reserved.
//
#include
"LenovoXCC.h"
#include
"timestamp.h"
#include
<iostream>
#include
<cstring>
void
printbuf
(
std
::
string
header
,
uint8_t
*
buf
,
int
len
)
{
std
::
cout
<<
header
<<
" ["
<<
len
<<
"]"
<<
std
::
hex
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
std
::
cout
<<
" "
<<
(
int
)
buf
[
i
];
}
std
::
cout
<<
std
::
endl
;
}
LenovoXCC
::
LenovoXCC
(
IPMIHost
*
host
)
{
_host
=
host
;
_handle
=
0
;
}
LenovoXCC
::~
LenovoXCC
()
{}
int
LenovoXCC
::
getSingleEnergy
(
uint64_t
&
timeStamp
,
uint64_t
&
energy
)
{
uint8_t
buf
[
256
];
uint8_t
getSingleEnergyCmd
[]
=
{
0x00
,
0x3a
,
0x32
,
0x04
,
0x02
,
0x00
,
0x00
,
0x00
};
int
len
=
-
1
;
try
{
len
=
_host
->
sendRawCmd
(
getSingleEnergyCmd
,
sizeof
(
getSingleEnergyCmd
),
buf
,
sizeof
(
buf
));
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
1
;
}
if
((
len
==
16
)
&&
(
buf
[
0
]
==
0x32
)
&&
(
buf
[
1
]
==
0x00
))
{
uint32_t
ts1
;
uint16_t
ts2
;
memcpy
(
&
ts1
,
&
buf
[
10
],
sizeof
(
ts1
));
memcpy
(
&
ts2
,
&
buf
[
14
],
sizeof
(
ts2
));
timeStamp
=
S_TO_NS
(
ts1
);
if
(
ts2
<
1000
)
{
timeStamp
+=
MS_TO_NS
(
ts2
);
}
uint32_t
joules
;
uint16_t
mJoules
;
memcpy
(
&
joules
,
&
buf
[
4
],
sizeof
(
joules
));
memcpy
(
&
mJoules
,
&
buf
[
8
],
sizeof
(
mJoules
));
energy
=
((
uint32_t
)
joules
)
*
1000
;
if
(
mJoules
<
1000
)
{
energy
+=
mJoules
;
}
return
0
;
}
return
-
1
;
}
int64_t
LenovoXCC
::
getDrift
()
{
int64_t
drift
=
0
;
uint64_t
xccTs
,
dummy
;
uint64_t
sysTs1
=
getTimestamp
();
if
(
getSingleEnergy
(
xccTs
,
dummy
)
==
0
)
{
uint64_t
sysTs2
=
getTimestamp
();
drift
=
sysTs1
+
(
sysTs2
-
sysTs1
)
/
2
-
xccTs
;
}
return
drift
;
}
int
LenovoXCC
::
openDatastore
()
{
if
(
_handle
)
{
closeDatastore
();
}
uint8_t
buf
[
256
];
uint8_t
getHandleCmd
[]
=
{
0x00
,
0x2e
,
0x90
,
0x66
,
0x4a
,
0x00
,
0x01
,
0x01
,
0x01
,
0xF0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x70
,
0x77
,
0x72
,
0x5f
,
0x6d
,
0x65
,
0x74
,
0x65
,
0x72
};
int
len
=
-
1
;
try
{
len
=
_host
->
sendRawCmd
(
getHandleCmd
,
sizeof
(
getHandleCmd
),
buf
,
sizeof
(
buf
));
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
255
;
}
//printbuf("open", buf, len);
if
((
len
==
9
)
&&
(
buf
[
0
]
==
0x90
)
&&
(
buf
[
1
]
==
0x00
))
{
memcpy
(
&
_handle
,
&
buf
[
5
],
sizeof
(
_handle
));
return
0
;
}
else
{
return
-
1
;
}
}
int
LenovoXCC
::
closeDatastore
()
{
if
(
!
_handle
)
{
return
2
;
}
uint8_t
buf
[
256
];
uint8_t
closeHandleCmd
[]
=
{
0x00
,
0x2e
,
0x90
,
0x66
,
0x4a
,
0x00
,
0x05
,
0xff
,
0xff
,
0xff
,
0xff
};
memcpy
(
&
closeHandleCmd
[
7
],
&
_handle
,
sizeof
(
_handle
));
int
len
=
-
1
;
try
{
len
=
_host
->
sendRawCmd
(
closeHandleCmd
,
sizeof
(
closeHandleCmd
),
buf
,
sizeof
(
buf
));
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
255
;
}
//printbuf("close", buf, len);
if
((
len
==
5
)
&&
(
buf
[
0
]
==
0x90
)
&&
(
buf
[
1
]
==
0x00
))
{
_handle
=
0
;
return
0
;
}
else
{
return
-
1
;
}
}
int
LenovoXCC
::
readDatastoreRange
(
uint32_t
offset
,
uint16_t
count
,
uint8_t
*
buf
,
uint16_t
bufLen
)
{
uint8_t
getDataCmd
[]
=
{
0x00
,
0x2e
,
0x90
,
0x66
,
0x4a
,
0x00
,
0x02
,
0xff
,
0xff
,
0xff
,
0xff
,
0x00
,
0x00
,
0x00
,
0x00
,
0x10
,
0x00
};
memcpy
(
&
getDataCmd
[
7
],
&
_handle
,
sizeof
(
_handle
));
memcpy
(
&
getDataCmd
[
11
],
&
offset
,
sizeof
(
offset
));
memcpy
(
&
getDataCmd
[
15
],
&
count
,
sizeof
(
count
));
int
len
=
-
1
;
try
{
len
=
_host
->
sendRawCmd
(
getDataCmd
,
sizeof
(
getDataCmd
),
buf
,
bufLen
);
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
-
1
;
}
if
((
len
>=
2
)
&&
(
buf
[
0
]
==
0x90
)
&&
(
buf
[
1
]
==
0x00
))
{
//printbuf("readDataStoreRange", buf, len);
return
len
;
}
else
{
return
-
1
;
}
}
uint64_t
LenovoXCC
::
readDatastoreTimestamp
()
{
uint8_t
buf
[
256
];
int
len
=-
1
;
try
{
len
=
readDatastoreRange
(
0
,
16
,
buf
,
sizeof
(
buf
));
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
0
;
}
if
(
len
>=
20
)
{
uint32_t
ts1
;
uint16_t
ts2
;
uint64_t
ts
;
uint64_t
index
;
memcpy
(
&
ts1
,
&
buf
[
7
],
sizeof
(
ts1
));
memcpy
(
&
ts2
,
&
buf
[
11
],
sizeof
(
ts2
));
memcpy
(
&
index
,
&
buf
[
15
],
sizeof
(
index
));
ts
=
(
uint64_t
)
ts1
*
1000
+
index
*
10
;
if
(
ts2
<
1000
)
{
ts
+=
ts2
;
}
ts
=
MS_TO_NS
(
ts
);
return
ts
;
}
else
{
return
0
;
}
}
int
LenovoXCC
::
readDatastorePower
(
std
::
vector
<
uint16_t
>&
readings
)
{
uint8_t
buf
[
256
];
try
{
for
(
uint16_t
offset
=
16
;
offset
<
6016
;
offset
+=
200
)
{
int
len
=
readDatastoreRange
(
offset
,
200
,
buf
,
sizeof
(
buf
));
if
(
len
>=
0
)
{
uint16_t
n
=
(
buf
[
5
]
|
buf
[
6
]
<<
8
)
/
2
;
uint16_t
*
buf16
=
(
uint16_t
*
)
&
buf
[
7
];
readings
.
insert
(
readings
.
end
(),
buf16
,
buf16
+
n
);
}
}
}
catch
(
const
std
::
exception
&
e
)
{
throw
e
;
return
1
;
}
if
(
readings
.
size
())
{
return
0
;
}
else
{
return
-
1
;
}
}
dcdbpusher/sensors/ipmi/LenovoXCC.h
0 → 100644
View file @
53a60288
//
// LenovoXCC.hpp
// dcdb
//
// Created by Ott, Michael on 21.08.19.
// Copyright © 2019 LRZ. All rights reserved.
//
#ifndef LenovoXCC_hpp
#define LenovoXCC_hpp
#include
<cstdint>
#include
"IPMIHost.h"
class
LenovoXCC
{
public:
LenovoXCC
(
IPMIHost
*
host
);
virtual
~
LenovoXCC
();
int
getSingleEnergy
(
uint64_t
&
timeStamp
,
uint64_t
&
energy
);
int64_t
getDrift
();
int
openDatastore
();
int
closeDatastore
();
uint64_t
readDatastoreTimestamp
();
int
readDatastorePower
(
std
::
vector
<
uint16_t
>&
readings
);
private:
int
readDatastoreRange
(
uint32_t
offset
,
uint16_t
count
,
uint8_t
*
buf
,
uint16_t
bufLen
);
IPMIHost
*
_host
;
uint32_t
_handle
;
};
#endif
/* LenovoXCC_hpp */
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment