Supervising motherboard sensory data as
fan speeds or CPU and board temperatures
in Python can be done with help of the MBM 5
utility available at
http://mbm.livewiredev.com/.
This utility exposes data got from the hardware
sensors in a shared memory area for querying
by another applications.
The pyMBM.py script provided below prints
excerpts of the content of the by MBM 5
in shared memory area provided data
and can be used as a starting point
for writing own scripts which need to
query motherboard sensory data or
as inspiration for creating an
appropriate pyMBM Python module.
Claudio Grondi
print
print ' pyMBM.py ver. 0.10 2005-04-08 '
print '*** ************************************************ ***'
print '*** THIS code accesses shared memory area exposed by ***'
print '*** MBM 5 (MotherBoard Monitor) ***'
print '*** install and run MBM 5 before using this script ***'
print '*** MBM 5 home:
http://mbm.livewiredev.com ***'
print '*** Port of the MBM API to Python by Claudio Grondi ***'
print '***
http://www.python.org/moin/ClaudioGrondi ***'
print '*** ************************************************ ***'
# centralized settings for portability and upgradability
SENSOR_INDEX_LENGTH = 10
SENSOR_INFO_LENGTH = 100
SENSOR_NAME_LEN = 12
TIME_STRING_LENGTH = 41
MBM_PATHNAME_LENGTH = 256
SMBUSNAME_STRING_LENGTH = 41
PADDING1_SIZE_BYTES = 3
PADDING2_SIZE_BYTES = 4
PADDING3_SIZE_BYTES = 8
#define BT_ISA "type_isa"
#define BT_SMBUS "type_smbus"
#define BT_VIA686ABUS "type_via686abus"
#define BT_DIRECTIO "type_directio"
#define BT_UNKNOWN "type_unknown"
# typedef enum { btISA = 0, btSMBus, btVIA686ABus, btDirectIO } bus_t;
bus_t = [
"ISA " # 0
,"SMBus " # 1
,"Via686aBus" # 2
,"DirectIO " # 3
]
#define SMBT_INTEL "type_intel"
#define SMBT_AMD "type_amd"
#define SMBT_ALI "type_ali"
#define SMBT_NFORCE "type_nforce"
#define SMBT_SIS "type_sis"
#define SMBT_UNK BT_UNKNOWN
# typedef enum { smtSMBIntel = 0, smtSMBAMD, smtSMBALi, smtSMBNForce,
smtSMBSIS } smb_t;
smb_t = [
"Intel " # 0
,"AMD " # 1
,"Ali " # 2
,"nForce" # 3
,"sis " # 4
]
#define ST_UNKNOWN BT_UNKNOWN
#define ST_TEMPERATURE "type_temperature"
#define ST_VOLTAGE "type_voltage"
#define ST_FAN "type_fan"
#define ST_MHZ "type_mhz"
#define ST_PERCENTAGE "type_percentage"
# typedef enum { stUnknown = 0, stTemperature, stVoltage, stFan, stMhz,
stPercentage } sensor_t;
sensor_t = [
"unknown " # 0
,"temperature" # 1
,"voltage " # 2
,"fan " # 3
,"mhz " # 4
,"percentage " # 5
]
from ctypes import *
class index(Structure):
_fields_ = [
("_type" , c_int ) # type of sensor
,("_count" , c_int ) # number of sensor for that type
]
class sensor(Structure):
_fields_ = [
("_type" , c_ubyte ) # type of sensor
,("_name" , c_ubyte * SENSOR_NAME_LEN ) # name of sensor
,("_padding1", c_ubyte * PADDING1_SIZE_BYTES ) # padding of 3 byte
,("_current" , c_double ) # current value
,("_low" , c_double ) # lowest readout
,("_high" , c_double ) # highest readout
,("_readout" , c_long ) # total number of readout
,("_padding2", c_ubyte * PADDING2_SIZE_BYTES ) # padding of 4 byte
,("_total" , c_double ) # actual a long double - total amout of
all readouts
,("_padding3", c_ubyte * PADDING3_SIZE_BYTES ) # padding of 6 byte
,("_alarm1" , c_double ) # temp & fan: low alarm; voltage: % off;
,("_alarm2" , c_double ) # temp: high alarm
]
class info(Structure):
_fields_ = [
("_smbBase" , c_short ) # SMBus base address
,("_smbType" , c_ubyte ) # bus_t variant of SMBus/Isa bus used to
access chip
# typedef enum
{btISA=0,btSMBus,btVIA686ABus,btDirectIO} bus_t;
,("_smbCode" , c_ubyte ) # smb_t variant of SMBus sub type, Intel,
AMD or ALi
# typedef enum
{smtSMBIntel=0,smtSMBAMD,smtSMBALi,smtSMBNForce,smtSMBSIS} smb_t;
,("_smbAddr" , c_ubyte ) # Address of sensor chip on SMBus
,("_smbName" , c_ubyte * SMBUSNAME_STRING_LENGTH ) # Nice name for
SMBus
,("_isaBase" , c_short ) # ISA base address of sensor chip on ISA
,("_chipType" , c_int ) # Chip nr, connects with Chipinfo.ini
,("_voltageSubType", c_ubyte ) # Subvoltage option selected
]
class data_t(Structure):
_fields_ = [
("_version", c_double ) # version number (example:
51090)
,("_index" , index * SENSOR_INDEX_LENGTH ) # Sensor index
,("_sensor" , sensor * SENSOR_INFO_LENGTH ) # sensor info
,("_info" , info ) # misc. info
,("_start" , c_ubyte * TIME_STRING_LENGTH ) # start time,
TIME_STRING_LENGTH = 41
,("_current", c_ubyte * TIME_STRING_LENGTH ) # current time
,("_path" , c_ubyte * MBM_PATHNAME_LENGTH ) # MBM path
]
FILE_MAP_READ = 2
strNameOfSharedMemoryAreaToAccess = "$M$B$M$5$S$D$"
handle = windll.kernel32.OpenFileMappingA(FILE_MAP_READ, 0,
strNameOfSharedMemoryAreaToAccess)
if not handle:
raise WinError()
addr = windll.kernel32.MapViewOfFile(
handle
,FILE_MAP_READ
,0
,0
,0
)
if not addr:
raise WinError()
obj_data_t = data_t.from_address(addr)
# obj_data_t holds the entire shared memory area content which can be
accessed
# now from within Python code like it is done below:
if(__name__ == '__main__'):
print
print '_version ', obj_data_t._version
print
# print '_index ', obj_data_t._index
itemCounter = 0
for item in obj_data_t._index:
itemCounter += 1
print '_index[%2i]._type ='%itemCounter, sensor_t[item._type],
'_index._count =',repr(item._count)
print
# print '_sensor ', obj_data_t._sensor
itemCounter = 0
for item in obj_data_t._sensor:
itemCounter += 1
print '_sensor[%3i]._type ='%itemCounter, sensor_t[item._type],
strSensorName = ''
for subitem in item._name:
strSensorName += chr(subitem)
print ' ._name =', strSensorName,
print ' ._current = %7.2f'%item._current, ' ._low = %7.2f'%item._low,
' ._high = %7.2f'%item._high
print
# print '_info ', obj_data_t._info
print '_info._smbType =', bus_t[obj_data_t._info._smbType]
print '_info._smbCode =', smb_t[obj_data_t._info._smbCode]
print
print '_start ',
strStart = ''
for char in obj_data_t._start:
strStart += chr(char)
print strStart
print '_current ',
strCurrent = ''
for char in obj_data_t._current:
strCurrent += chr(char)
print strCurrent,
print
print '_path ',
strPath = ''
for char in obj_data_t._path:
strPath += chr(char)
print strPath,
windll.kernel32.UnmapViewOfFile(addr)
windll.kernel32.CloseHandle(handle)
print
raw_input(' (exit with ENTER) #> OK? ')
#:if