import logging
import os.path
from configparser import ConfigParser
from ctypes import byref, c_float, c_int32, c_uint16, c_uint32, create_string_buffer, memset, sizeof
from os import PathLike
from re import match
from string import ascii_uppercase
from typing import Any, Dict, Iterable, List, NamedTuple, Union
from .core import PSP, get_psp_exc_msg
from .exc import (
PSPError,
PSPInvalid,
PSPNotOpened,
PSPNotSupport,
)
from .lmbinc import (
ERR_Invalid,
ERR_NotOpened,
ERR_NotSupport,
ERR_Success,
HWM_RISER_12V,
HWM_RISER_12VEXT,
HWM_RISER_FAN1,
HWM_RISER_TEMP1,
HWM_RISER_TEMPLocal,
HWM_RISER_VCC,
)
from .lmbipmi import (
HWM_TYPE_NONE,
HWM_TYPE_SIO,
HWM_TYPE_IPMI,
HWM_TYPE_SMBUS,
HWM_TYPE_AST1400,
IPMISensorInfo,
)
from .lmbsid import HWM_DISPLAY_NAME_MAPPING, HWMSensorItemV23, HWMSensorItemV30
from .sdk_dll import DLL
logger = logging.getLogger(__name__)
SUPPORTED_PLATFORMS = ("LEB-2680", "LEB-7242", "LEC-2290", "LEC-7230", "NCA-2510", "V3S", "V6S",)
UNSUPPORTED_PLATFORMS = ()
ALARM = "\033[1;31mALARM\033[m"
DEFAULT_HWM_CONF = "/etc/lanner/hwm.conf"
class _HWMSensorMsgModel(NamedTuple):
"""To store Hardware Monitor sensor message."""
value: Union[int, float, str]
unit: str
[docs]
class HWMSensorModel(NamedTuple):
"""To store Hardware Monitor sensor information."""
sid: int
name: str
display_name: str
value: Any
unit: str
[docs]
def to_dict(self) -> Dict[str, Any]:
"""Convert to dict."""
return dict(self._asdict())
[docs]
class HWM:
"""
Hardware Monitor.
:param bool check_platform:
Set to :data:`True` to check if the platform supports this feature.
Defaults to :data:`False` for better compatibility.
:raises PSPNotSupport: This function is not supported
(when ``check_platform`` is set to :data:`True`).
:raises NotImplementedError: It has not been verified to run on this platform
(when ``check_platform`` is set to :data:`True`).
"""
def __init__(self, check_platform: bool = False) -> None:
self._dw_sensor_type = c_int32(0)
self._version = DLL().get_version()
if not check_platform:
return
if self._version.platform_id in SUPPORTED_PLATFORMS:
pass
elif self._version.platform_id in UNSUPPORTED_PLATFORMS:
raise PSPNotSupport("Not supported on this platform")
else:
raise NotImplementedError
[docs]
def get_cpu_temp(self, num: int) -> int:
"""
Read temperature of the CPU processor (°C).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_cpu_temp(1)
40
:param int num: selects CPU number
:return: the current temperature value of the CPU
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetCpuTemp(num, byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_GetCpuTemp", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_TEMP_CPU{num:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(f_temp.value):d}")
return int(f_temp.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_sys_temp(self, num: int) -> int:
"""
Read temperature of the system (°C).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_sys_temp(1)
41
:param int num: selects System sensor number
:return: the current temperature value of the system
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetSysTemp(num, byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_GetSysTemp", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_TEMP_SYS{num:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(f_temp.value):d}")
return int(f_temp.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_core_volt(self, num: int) -> float:
"""
Read the CPU Vcore voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_core_volt(1)
0.856
:param int num: selects CPU number
:return: the current voltage of CPU Vcore
:rtype: float
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetVcore(num, byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_GetVcore", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_VCORE_CPU{num:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_12v_volt(self) -> float:
"""
Read the positive 12V voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_12v_volt()
12.232
:return: the current voltage of positive 12V
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_Get12V(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_Get12V", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_P12V"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_5v_volt(self) -> float:
"""
Read the positive 5V voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_5v_volt()
5.087
:return: the current voltage of positive 5V
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_Get5V(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_Get5V", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_P5V"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_3v3_volt(self) -> float:
"""
Read the positive 3.3V voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_3v3_volt()
3.328
:return: the current voltage of positive 3.3V
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_Get3V3(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_Get3V3", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_P3V3"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_5vsb_volt(self) -> float:
"""
Read the positive 5V standby power (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_5vsb_volt()
5.003
:return: the current voltage of positive 5V standby power
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_Get5Vsb(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_Get5Vsb", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_P5VSB"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_3v3sb_volt(self) -> float:
"""
Read the positive 3V/3.3V standby power (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_3v3sb_volt()
3.344
:return: the current voltage of positive 3.3V standby power
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_Get3V3sb(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_Get3V3sb", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_P3V3SB"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_bat_volt(self) -> float:
"""
Read the battery voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_bat_volt()
3.168
:return: the current voltage of the battery
:rtype: float
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetVbat(byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_GetVbat", i_ret)
if i_ret == ERR_Success:
# hwm_id = "HWMID_VOLT_VBAT"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_dimm_volt(self, ch: int) -> float:
"""
Read the DRAM voltage (V).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_dimm_volt()
1.096
:param int ch: the DDR channel
:return: the current voltage of the DDR channel
:rtype: float
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(ch, int):
raise TypeError("'num' type must be int")
f_temp = c_float()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetVDDR(ch, byref(f_temp))
msg = get_psp_exc_msg("LMB_HWM_GetVDDR", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_VOLT_DDRCH{ch:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {f_temp.value:2.3f}")
return float(f"{f_temp.value:2.3f}")
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_psu_volt(self, num: int) -> int:
"""
Read the power supply AC input (V).
:param int num: the AC power supply number which is described in user manual
:return: the AC power voltage
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# TODO: Example
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
w_data = c_uint16()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetPowerSupply(num, byref(w_data))
msg = get_psp_exc_msg("LMB_HWM_GetPowerSupply", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_PSU{num:d}_VOLTIN"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {w_data.value:d}")
return w_data.value
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_cpu_fan_speed(self, num: int) -> int:
"""
Get CPU fan speed (RPM).
:param int num: the number of fan
:return: the fan speed
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# TODO: Example
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
w_rpm = c_uint16()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetCpuFan(num, byref(w_rpm))
msg = get_psp_exc_msg("LMB_HWM_GetCpuFan", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_RPM_FanCpu{num:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(w_rpm.value):d}")
return int(w_rpm.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_sys_fan_speed(self, num: int) -> int:
"""
Get SYS fan speed (RPM).
:param int num: the number of fan
:return: the fan speed
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# TODO: Example
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
w_rpm = c_uint16()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetSysFan(num, byref(w_rpm))
msg = get_psp_exc_msg("LMB_HWM_GetSysFan", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_RPM_FanSys{num:d}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(w_rpm.value):d}")
return int(w_rpm.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_fan_speed(self, num: int) -> int:
"""
Read the fan speed which was assigned (RPM).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_fan_speed(1)
7297
:param int num: the fan index number which is described in user manual
:return: the fan speed
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
w_rpm = c_uint16()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetFanSpeed(num, byref(w_rpm))
msg = get_psp_exc_msg("LMB_HWM_GetFanSpeed", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_RPM_Fan{num:d}A"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(w_rpm.value):d}")
return int(w_rpm.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_fan_speed_ex(self, num: int, ex_num: int) -> int:
"""
Read the fan speed which was assigned (RPM).
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_fan_speed_ex(1, 1)
7258
:param int num: the fan index number which is described in user manual
:param int ex_num: the fan sub-index number which is described in user manual (A=1, B=2, and so on)
:return: the fan speed
:rtype: int
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(num, int):
raise TypeError("'num' type must be int")
if not isinstance(ex_num, int):
raise TypeError("'ex_num' type must be int")
w_rpm = c_uint16()
with PSP() as psp:
i_ret = psp.lib.LMB_HWM_GetFanSpeedEx(num, byref(w_rpm), ex_num)
msg = get_psp_exc_msg("LMB_HWM_GetFanSpeedEx", i_ret)
if i_ret == ERR_Success:
# hwm_id = f"HWMID_RPM_Fan{num:d}{ascii_uppercase[ex_num - 1]}"
# logger.debug(f"{HWM_DISPLAY_NAME_MAPPING[hwm_id]} = {int(w_rpm.value):d}")
return int(w_rpm.value)
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_sensor_name(self, sid: int) -> str:
"""
Get the sensor ID name by PSP define.
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_sensor_name(0)
'HWMID_TEMP_CPU1'
:param int sid: sensor index number
:return: the sensor name of the designated
:rtype: str
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(sid, int):
raise TypeError("'sid' type must be int")
# Check value.
if self._version.dll_major == 2 and self._version.dll_minor == 1:
pass # Can not check.
elif self._version.dll_major == 2 and self._version.dll_minor == 3:
if sid not in range(HWMSensorItemV23.HWMID_TOTAL.value):
raise PSPInvalid(f"'sid' value must be in range({HWMSensorItemV23.HWMID_TOTAL.value})")
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
if sid not in range(HWMSensorItemV30.HWMID_TOTAL.value):
raise PSPInvalid(f"'sid' value must be in range({HWMSensorItemV30.HWMID_TOTAL.value})")
else:
raise NotImplementedError
str_id_name = create_string_buffer(50)
memset(str_id_name, 0, 30)
with PSP() as psp:
if self._version.dll_major == 2 and self._version.dll_minor in (1, 2, 3):
i_ret = psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
i_ret = psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
msg = get_psp_exc_msg("LMB_HWM_GetSensorName", i_ret)
if i_ret == ERR_Success:
name: str = str_id_name.value.decode(errors="ignore")
# logger.debug(f"Sensor ID={sid:d}, name is \"{name}\"")
return name
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def get_sensor_msg(self, sid: int) -> str:
"""
Read the sensor report message.
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.get_sensor_msg(0)
'41000 mCelsius'
:param int sid: sensor index number
:return: the message of the designated
:rtype: str
:raises TypeError: The input parameters type error.
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
# Check type.
if not isinstance(sid, int):
raise TypeError("'sid' type must be int")
# Check value.
if self._version.dll_major == 2 and self._version.dll_minor == 1:
pass
elif self._version.dll_major == 2 and self._version.dll_minor == 3:
if sid not in range(HWMSensorItemV23.HWMID_TOTAL.value):
raise PSPInvalid(f"'sid' value must be in range({HWMSensorItemV23.HWMID_TOTAL.value})")
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
if sid not in range(HWMSensorItemV30.HWMID_TOTAL.value):
raise PSPInvalid(f"'sid' value must be in range({HWMSensorItemV30.HWMID_TOTAL.value})")
else:
raise NotImplementedError
str_msg = create_string_buffer(50)
memset(str_msg, 0, 30)
with PSP() as psp:
if self._version.dll_major == 2 and self._version.dll_minor in (1, 2, 3):
i_ret = psp.lib.LMB_HWM_GetSensorReport(sid, str_msg)
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
i_ret = psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg))
msg = get_psp_exc_msg("LMB_HWM_GetSensorReport", i_ret)
if i_ret == ERR_Success:
message: str = str_msg.value.decode(errors="ignore")
# logger.debug(f"Sensor ID={sid:d}, message is \"{message}\"")
return message
elif i_ret == ERR_NotOpened:
raise PSPNotOpened(msg)
elif i_ret == ERR_Invalid:
raise PSPInvalid(msg)
elif i_ret == ERR_NotSupport:
raise PSPNotSupport(msg)
else:
raise PSPError(msg)
[docs]
def list_supported_sensors(self, with_graphic_card: bool = False) -> List[HWMSensorModel]:
"""
List all supported sensors.
Example:
.. code-block:: pycon
>>> hwm = HWM()
>>> sensors = hwm.list_supported_sensors()
>>> for s in sensors:
... s.to_dict()
{'sid': 0, 'name': 'HWMID_TEMP_CPU1', 'display_name': 'CPU 1 temperature', 'value': 40, 'unit': 'C'}
{'sid': 2, 'name': 'HWMID_TEMP_SYS1', 'display_name': 'SYS 1 temperature', 'value': 42, 'unit': 'C'}
.
.
.
{'sid': 12, 'name': 'HWMID_VOLT_DDRCH1', 'display_name': 'DDR channel 1', 'value': 1.096, 'unit': 'V'}
>>> for s in sensors:
... print(f"{s.display_name} = {s.value} {s.unit}")
...
CPU-1 temperature = 40 C
SYS-1 temperature = 42 C
.
.
.
VDIMM-1 = 1.096 V
:param bool with_graphic_card:
Set to :data:`True` to merge graphics card information (if supported).
Defaults to :data:`False` for better performance.
:return: list of supported sensor model
:rtype: List[HWMSensorModel]
:raises PSPNotOpened: The library is not ready or opened yet.
:raises PSPInvalid: The input parameter is out of range.
:raises PSPNotSupport: This platform does not support this function.
:raises PSPError: General PSP functional error.
"""
if self._version.dll_major == 2 and self._version.dll_minor == 1:
total = 100
elif self._version.dll_major == 2 and self._version.dll_minor in (2, 3):
total = HWMSensorItemV23.HWMID_TOTAL.value
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
total = HWMSensorItemV30.HWMID_TOTAL.value
else:
raise NotImplementedError
supported_sensors = []
for i in range(total):
try:
message = self.get_sensor_msg(i)
except PSPError:
continue
name = self.get_sensor_name(i)
display_name = HWM_DISPLAY_NAME_MAPPING.get(name, None)
if display_name is None:
continue
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=i,
name=name,
display_name=display_name,
value=parsed_msg.value,
unit=parsed_msg.unit))
if with_graphic_card:
# For LEC-2290 with PSP version 2.1.X:
if self._version.platform_id in ("LEC-2290",) and self._version.dll_major == 2 and self._version.dll_minor == 1:
str_msg = create_string_buffer(30)
with PSP() as psp:
for x in range(1, 3):
sid = HWM_RISER_TEMP1 + x - 1
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mCelsius"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card Temp-{x}",
value=parsed_msg.value,
unit=parsed_msg.unit))
for x in range(1, 3):
sid = HWM_RISER_FAN1 + x - 1
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 RPM"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card FAN-{x}",
value=parsed_msg.value,
unit=parsed_msg.unit))
# For PSP version 2.1.2:
if self._version.dll_build == 2:
sid = HWM_RISER_TEMPLocal
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mCelsius"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card Temp-Chip",
value=parsed_msg.value,
unit=parsed_msg.unit))
sid = HWM_RISER_VCC
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card 3.3V",
value=parsed_msg.value,
unit=parsed_msg.unit))
sid = HWM_RISER_12V
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card 12V",
value=parsed_msg.value,
unit=parsed_msg.unit))
sid = HWM_RISER_12VEXT
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
parsed_msg = self._parse_sensor_msg(msg=message)
supported_sensors.append(HWMSensorModel(sid=sid,
name="",
display_name=f"Graphic Card 12VEXT",
value=parsed_msg.value,
unit=parsed_msg.unit))
return supported_sensors
@classmethod
def _parse_sensor_msg(cls, msg: str) -> _HWMSensorMsgModel:
"""
Parse sensor message from :meth:`get_sensor_name`.
:param str msg: Output message from :meth:`get_sensor_name`.
:return: The :class:`_HWMSensorMsgModel` model.
:rtype: _HWMSensorMsgModel
"""
value_str, unit = msg.strip().split()
if unit in ("mCelsius",):
value = int(value_str) // 1000
unit = "C"
elif unit in ("mVolts",):
value = int(value_str) / 1000
unit = "V"
elif unit in ("mAmps",):
value = int(value_str) / 1000
unit = "A"
elif unit in ("mWatts",):
value = int(value_str) / 1000
unit = "W"
elif unit in ("Volts",):
value = int(value_str)
unit = "V"
elif unit in ("RPM",):
value = int(value_str)
unit = "RPM"
elif unit in ("Status",):
value = value_str
unit = "Status"
else:
value = value_str
# NotImplementedError
return _HWMSensorMsgModel(value=value, unit=unit)
def testhwm(
self,
conf_path: Union[
str, bytes, "PathLike[str]", "PathLike[bytes]",
Iterable[Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]],
] = "/opt/lanner/psp/bin/amd64/utils/hwm.conf",
) -> None:
"""
For hardware monitor testing.
Example for PSP version < 2.3:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.testhwm()
CPU-1 temperature = 40 C (min = 30 C, max = 85 C)
SYS-1 temperature = 41 C (min = 25 C, max = 65 C)
CPU-1 Vcore = 0.856 V (min = 0.600 V, max = 2.000 V)
5V = 5.087 V (min = 4.500 V, max = 5.500 V)
3.3V = 3.350 V (min = 2.970 V, max = 3.630 V)
Vbat = 3.168 V (min = 3.000 V, max = 3.300 V)
VDDR = 1.104 V (min = 1.080 V, max = 1.320 V)
or PSP version >= 2.3:
.. code-block:: pycon
>>> hwm = HWM()
>>> hwm.testhwm()
===> Hardware Monitor Type is SuperIO <===
Sensor Name Value LowCritical UpperCritical Result
-------------------------------------------------------------------------
SYS1 Temp = 40 C (min = -5 C, max = 70 C)
SYS2 Temp = 39 C (min = -5 C, max = 70 C)
Vcore = 0.784 V (min = 0.450 V, max = 1.350 V)
VGFX = 0.824 V (min = 0.450 V, max = 1.350 V)
12V = 12.232 V (min = 11.400 V, max = 12.600 V)
5V = 5.003 V (min = 4.750 V, max = 5.250 V)
VCC3V = 3.344 V (min = 3.130 V, max = 3.460 V)
VSB3V = 3.344 V (min = 3.130 V, max = 3.460 V)
VBAT = 3.280 V (min = 2.000 V, max = 3.470 V)
:type conf_path:
str or bytes or PathLike[str] or PathLike[bytes]
or Iterable[str or bytes or PathLike[str] or PathLike[bytes]]
:param conf_path:
path of the `hwm.conf`
"""
if self._version.dll_major == 2 and self._version.dll_minor == 1:
self._hwm_tst_v21(conf_path)
elif self._version.dll_major == 2 and self._version.dll_minor == 3:
self._hwm_tst_v23(conf_path)
elif self._version.dll_major == 3 and self._version.dll_minor == 0:
self._hwm_tst_v30(conf_path)
else:
raise NotImplementedError
def _hwm_tst_v21(
self,
conf_path: Union[
str, bytes, "PathLike[str]", "PathLike[bytes]",
Iterable[Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]],
],
) -> None:
"""
For PSP version == '2.1.X'.
"""
f_temp = c_float()
w_data = c_uint16()
w_rpm = c_uint16()
cp = ConfigParser()
cp.read(conf_path)
with PSP() as psp:
# Temperature area
if psp.lib.LMB_HWM_GetCpuTemp(1, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_CPU1_Temp", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_CPU1_Temp", "max", fallback="0"))
msg = f"CPU-1 temperature = {int(f_temp.value):3d} C\t" \
f"(min = {min_:3.0f} C, max = {max_:3.0f} C)"
if f_temp.value < min_ or f_temp.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetCpuTemp(2, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_CPU2_Temp", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_CPU2_Temp", "max", fallback="0"))
msg = f"CPU-2 temperature = {int(f_temp.value):3d} C\t" \
f"(min = {min_:3.0f} C, max = {max_:3.0f} C)"
if f_temp.value < min_ or f_temp.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetSysTemp(1, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_SYS1_Temp", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_SYS1_Temp", "max", fallback="0"))
msg = f"SYS-1 temperature = {int(f_temp.value):3d} C\t" \
f"(min = {min_:3.0f} C, max = {max_:3.0f} C)"
if f_temp.value < min_ or f_temp.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetSysTemp(2, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_SYS2_Temp", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_SYS2_Temp", "max", fallback="0"))
msg = f"SYS-2 temperature = {int(f_temp.value):3d} C\t" \
f"(min = {min_:3.0f} C, max = {max_:3.0f} C)"
if f_temp.value < min_ or f_temp.value > max_:
msg += f" {ALARM}"
print(msg)
# Voltage area
if psp.lib.LMB_HWM_GetVcore(1, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_Core1_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_Core1_volt", "max", fallback="0"))
msg = f"CPU-1 Vcore = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetVcore(2, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_Core2_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_Core2_volt", "max", fallback="0"))
msg = f"CPU-2 Vcore = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_Get12V(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_12v_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_12v_volt", "max", fallback="0"))
msg = f"12V = {f_temp.value:7.3f} V\t\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_Get5V(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_5v_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_5v_volt", "max", fallback="0"))
msg = f"5V = {f_temp.value:7.3f} V\t\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_Get3V3(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_3v3_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_3v3_volt", "max", fallback="0"))
msg = f"3.3V = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_Get5Vsb(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_5vsb_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_5vsb_volt", "max", fallback="0"))
msg = f"5VSB = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_Get3V3sb(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_3v3sb_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_3v3sb_volt", "max", fallback="0"))
msg = f"3.3VSB = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetVbat(byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_vBat_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_vBat_volt", "max", fallback="0"))
msg = f"Vbat = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetVDDR(1, byref(f_temp)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_vddr_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_vddr_volt", "max", fallback="0"))
msg = f"VDDR = {f_temp.value:7.3f} V\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
round_up_buffer = int(f_temp.value * 1000)
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetPowerSupply(1, byref(w_data)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_PSU1_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_PSU1_volt", "max", fallback="0"))
msg = f"PowerSupply 1 AC voltage = {w_data.value:3d} V\t" \
f"(min = {min_:3.0f} V, max = {max_:3.0f} V)"
if w_data.value < min_ or w_data.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetPowerSupply(2, byref(w_data)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_PSU2_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_PSU2_volt", "max", fallback="0"))
msg = f"PowerSupply 2 AC voltage = {w_data.value:3d} V\t" \
f"(min = {min_:3.0f} V, max = {max_:3.0f} V)"
if w_data.value < min_ or w_data.value > max_:
msg += f" {ALARM}"
print(msg)
# Fan area
if psp.lib.LMB_HWM_GetCpuFan(1, byref(w_rpm)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_CPU1_RPM", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_CPU1_RPM", "max", fallback="0"))
msg = f"CPU FAN 1 speed = {w_rpm.value:5d} rpm\t" \
f"(min = {min_:5.0f} rpm, max = {max_:5.0f} rpm)"
if w_rpm.value < min_ or w_rpm.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetCpuFan(2, byref(w_rpm)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_CPU2_RPM", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_CPU2_RPM", "max", fallback="0"))
msg = f"CPU FAN 2 speed = {w_rpm.value:5d} rpm\t" \
f"(min = {min_:5.0f} rpm, max = {max_:5.0f} rpm)"
if w_rpm.value < min_ or w_rpm.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetSysFan(1, byref(w_rpm)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_SYS1_RPM", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_SYS1_RPM", "max", fallback="0"))
msg = f"SYS FAN 1 speed = {w_rpm.value:5d} rpm\t" \
f"(min = {min_:5.0f} rpm, max = {max_:5.0f} rpm)"
if w_rpm.value < min_ or w_rpm.value > max_:
msg += f" {ALARM}"
print(msg)
if psp.lib.LMB_HWM_GetSysFan(2, byref(w_rpm)) == ERR_Success:
min_ = self._str_replace(cp.get("HWM_SYS2_RPM", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_SYS2_RPM", "max", fallback="0"))
msg = f"SYS FAN 2 speed = {w_rpm.value:5d} rpm\t" \
f"(min = {min_:5.0f} rpm, max = {max_:5.0f} rpm)"
if w_rpm.value < min_ or w_rpm.value > max_:
msg += f" {ALARM}"
print(msg)
# For LEC-2290 with PSP version 2.1.X:
if self._version.platform_id in ("LEC-2290",) and self._version.dll_major == 2 and self._version.dll_minor == 1:
for i in range(100, 0, -1): # Searching from behind will be faster.
name = self.get_sensor_name(i)
if name != "HWMID_VOLT_VCCGT":
continue
min_ = self._str_replace(cp.get("HWM_vccgt_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_vccgt_volt", "max", fallback="0"))
message = self.get_sensor_msg(sid=i)
value = self._parse_sensor_msg(msg=message).value
msg = f"VGT = {value:7.3f} V\t\t\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
break
print("\033[2;31m=================== Graphic Card Sensor Items ======================\033[m")
str_msg = create_string_buffer(30)
with PSP() as psp:
for x in range(1, 3):
sid = HWM_RISER_TEMP1 + x - 1
min_ = self._str_replace(cp.get("HWM_RISER_TEMP", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_RISER_TEMP", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mCelsius"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card Temp-{x:d} = {int(value):3d} C\t" \
f"(min = {min_:7.0f} C, max = {max_:7.0f} C)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
for x in range(1, 3):
sid = HWM_RISER_FAN1 + x - 1
min_ = self._str_replace(cp.get("HWM_RISER_FAN", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_RISER_FAN", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 RPM"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card FAN-{x:d} = {value:5d} rpm\t" \
f"(min = {min_:5.0f} rpm, max = {max_:5.0f} rpm)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
# For PSP version 2.1.2:
if self._version.dll_build == 2:
sid = HWM_RISER_TEMPLocal
min_ = self._str_replace(cp.get("HWM_RISER_LOCAL", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_RISER_LOCAL", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mCelsius"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card Temp-Chip = {int(value):3d} C\t" \
f"(min = {min_:7.0f} C, max = {max_:7.0f} C)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
sid = HWM_RISER_VCC
min_ = self._str_replace(cp.get("HWM_3v3_volt", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_3v3_volt", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card 3.3V = {value:7.3f} V\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
sid = HWM_RISER_12V
min_ = self._str_replace(cp.get("HWM_RISER_12v", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_RISER_12v", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card 12V = {value:7.3f} V\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
sid = HWM_RISER_12VEXT
min_ = self._str_replace(cp.get("HWM_RISER_12v", "min", fallback="0"))
max_ = self._str_replace(cp.get("HWM_RISER_12v", "max", fallback="0"))
if psp.lib.LMB_HWM_GetF75837(sid, str_msg) != ERR_NotSupport:
message: str = str_msg.value.decode(errors="ignore") or "0 mVolts"
value = self._parse_sensor_msg(msg=message).value
msg = f"Graphic Card 12VEXT = {value:7.3f} V\t" \
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)"
if value < min_ or value > max_:
msg += f" {ALARM}"
print(msg)
def _hwm_tst_v23(
self,
conf_path: Union[
str, bytes, "PathLike[str]", "PathLike[bytes]",
Iterable[Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]],
],
) -> None:
"""
For PSP version == '2.3.X'.
"""
show_ipmi_only = False
if os.path.isfile(conf_path):
print(f"\033[1;31m<Note> found {conf_path} file, critical value will change !!!\033[m")
else:
conf_path = DEFAULT_HWM_CONF
if os.path.isfile(conf_path):
print(f"\033[1;31m<Note> found {conf_path} file, critical value will change !!!\033[m")
cp = ConfigParser()
cp.read(conf_path)
with PSP() as psp:
psp.lib.LMB_HWM_GetSensorType(byref(self._dw_sensor_type))
if self._dw_sensor_type.value == HWM_TYPE_NONE:
print("\033[1;31m<Warning> Hardware Monitor Type is Unknown !!!\033[m")
return
elif self._dw_sensor_type.value == HWM_TYPE_IPMI:
show_ipmi_only = True
print("\033[1;34m===> Hardware Monitor Type is IPMI <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_AST1400:
print("\033[1;34m===> Hardware Monitor Type is AST-1400 <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_SMBUS:
print("\033[1;34m===> Hardware Monitor Type is SMBus <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_SIO:
print("\033[1;34m===> Hardware Monitor Type is SuperIO <===\033[m")
else:
print("\033[1;31m<Warning> Hardware Monitor Type is Unknown !!!\033[m")
return
print("Sensor Name Value LowCritical UpperCritical Result")
print("-------------------------------------------------------------------------")
# CPU Temperature
sid = HWMSensorItemV23.HWMID_TEMP_CPU1.value
for i in range(sid, sid + 4):
self._show_temperature_v23(i, cp)
# SYS Temperature
sid = HWMSensorItemV23.HWMID_TEMP_SYS1.value
for i in range(sid, sid + 4):
self._show_temperature_v23(i, cp)
# PCH Temperature
sid = HWMSensorItemV23.HWMID_TEMP_PCH.value
self._show_temperature_v23(sid, cp)
# CPU DIMM Temperature
sid = HWMSensorItemV23.HWMID_TEMP_DIMMP1A0.value
for i in range(sid, sid + 32):
self._show_temperature_v23(i, cp)
# CPU Vcore
sid = HWMSensorItemV23.HWMID_VCORE_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v23(i, cp)
# P12V
sid = HWMSensorItemV23.HWMID_VOLT_P12V.value
self._show_voltage_v23(sid, cp)
# P5V
sid = HWMSensorItemV23.HWMID_VOLT_P5V.value
self._show_voltage_v23(sid, cp)
# P3.3V
sid = HWMSensorItemV23.HWMID_VOLT_P3V3.value
self._show_voltage_v23(sid, cp)
# P5VSB
sid = HWMSensorItemV23.HWMID_VOLT_P5VSB.value
self._show_voltage_v23(sid, cp)
# P3.3VSB
sid = HWMSensorItemV23.HWMID_VOLT_P3V3SB.value
self._show_voltage_v23(sid, cp)
# VBAT
sid = HWMSensorItemV23.HWMID_VOLT_VBAT.value
self._show_voltage_v23(sid, cp)
# 1.05V
sid = HWMSensorItemV23.HWMID_VOLT_P1V05.value
self._show_voltage_v23(sid, cp)
# VCCIO
sid = HWMSensorItemV23.HWMID_VOLT_PVCCIO_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v23(i, cp)
# VCCSA
sid = HWMSensorItemV23.HWMID_VOLT_PVCCSA_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v23(i, cp)
# VNN
sid = HWMSensorItemV23.HWMID_VOLT_PVNN.value
self._show_voltage_v23(sid, cp)
# DDR Voltage
sid = HWMSensorItemV23.HWMID_VOLT_DDRCH1.value
for i in range(sid, sid + 8):
self._show_voltage_v23(i, cp)
# extern sensors
sid = HWMSensorItemV23.HWMID_PSU2_TEMP2.value + 1
for i in range(sid, HWMSensorItemV23.HWMID_TOTAL.value):
self._show_voltage_v23(i, cp)
sid = HWMSensorItemV23.HWMID_RPM_Fan1A.value
for i in range(10):
self._show_rpm_v23(i * 2 + sid, cp)
self._show_rpm_v23(i * 2 + sid + 1, cp)
# IPMI PSU
for i in range(2):
if show_ipmi_only:
print("\033[2;31m================ For PSU when BMC exist ==========================\033[m")
show_ipmi_only = False
# PSU VIn
sid = HWMSensorItemV23.HWMID_PSU1_VOLTIN.value + 11 * i
self._show_voltage_v23(sid, cp)
# PSU Vout
sid = HWMSensorItemV23.HWMID_PSU1_VOLTOUT.value + 11 * i
self._show_voltage_v23(sid, cp)
# PSU Current In
sid = HWMSensorItemV23.HWMID_PSU1_CURRENTIN.value + 11 * i
self._show_current_v23(sid, cp)
# PSU Current Out
sid = HWMSensorItemV23.HWMID_PSU1_CURRENTOUT.value + 11 * i
self._show_current_v23(sid, cp)
# PSU Power In
sid = HWMSensorItemV23.HWMID_PSU1_POWERIN.value + 11 * i
self._show_watts_v23(sid, cp)
# PSU Power Out
sid = HWMSensorItemV23.HWMID_PSU1_POWEROUT.value + 11 * i
self._show_watts_v23(sid, cp)
# PSU Fan 1
sid = HWMSensorItemV23.HWMID_PSU1_FAN1.value + 11 * i
self._show_rpm_v23(sid, cp)
# PSU Fan 2
sid = HWMSensorItemV23.HWMID_PSU1_FAN2.value + 11 * i
self._show_rpm_v23(sid, cp)
# PSU Temp 1
sid = HWMSensorItemV23.HWMID_PSU1_TEMP1.value + 11 * i
self._show_temperature_v23(sid, cp)
# PSU Temp 2
sid = HWMSensorItemV23.HWMID_PSU1_TEMP2.value + 11 * i
self._show_temperature_v23(sid, cp)
def _show_temperature_v23(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '2.3.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
udw_lo_critical = c_uint32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp)
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(udw_lo_critical), byref(udw_hi_critical))
min_ = udw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
temp = self._atoll(str_msg.value.decode()) / 1000
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = --N/A-- C, max = {int(max_):7d} C)", end="")
if temp > max_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = {int(min_):7d} C, max = --N/A-- C)", end="")
if temp < min_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = --N/A-- C, max = --N/A-- C)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = {int(min_):7d} C, max = {int(max_):7d} C)", end="")
if temp < min_ or temp > max_:
print(f" {ALARM}", end="")
print()
def _show_rpm_v23(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '2.3.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
udw_lo_critical = c_uint32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp)
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(udw_lo_critical), byref(udw_hi_critical))
min_ = udw_lo_critical.value
max_ = udw_hi_critical.value
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
rpm = self._atoll(str_msg.value.decode())
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = --N/A-- rpm, max = {int(max_):5d} rpm)", end="")
if rpm > max_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = {int(min_):5d} rpm, max = --N/A-- rpm)", end="")
if rpm < min_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = --N/A-- rpm, max = --N/A-- rpm)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = {int(min_):5d} rpm, max = {int(max_):5d} rpm)", end="")
if rpm < min_ or rpm > max_:
print(f" {ALARM}", end="")
print()
def _show_voltage_v23(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '2.3.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
udw_lo_critical = c_uint32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp)
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(udw_lo_critical), byref(udw_hi_critical))
min_ = udw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
volt = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(volt * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = --N/A-- V, max = {max_:7.3f} V)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = {min_:7.3f} V, max = --N/A-- V)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = --N/A-- V, max = --N/A-- V)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
def _show_current_v23(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '2.3.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
udw_lo_critical = c_uint32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp)
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(udw_lo_critical), byref(udw_hi_critical))
min_ = udw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
current = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(current * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = --N/A-- A, max = {max_:7.3f} A)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = {min_:7.3f} A, max = --N/A-- A)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = --N/A-- A, max = --N/A-- A)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = {min_:7.3f} A, max = {max_:7.3f} A)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
def _show_watts_v23(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '2.3.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
udw_lo_critical = c_uint32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp)
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name)
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(udw_lo_critical), byref(udw_hi_critical))
min_ = udw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
watts = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(watts * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = --N/A-- W, max = {max_:7.3f} W)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = {min_:7.3f} W, max = --N/A-- W)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = --N/A-- W, max = --N/A-- W)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = {min_:7.3f} W, max = {max_:7.3f} W)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
def _hwm_tst_v30(
self,
conf_path: Union[
str, bytes, "PathLike[str]", "PathLike[bytes]",
Iterable[Union[str, bytes, "PathLike[str]", "PathLike[bytes]"]],
],
) -> None:
"""
For PSP version == '3.0.X'.
"""
show_ipmi_only = False
if os.path.isfile(conf_path):
print(f"\033[1;31m<Note> found {conf_path} file, critical value will change !!!\033[m")
else:
conf_path = DEFAULT_HWM_CONF
if os.path.isfile(conf_path):
print(f"\033[1;31m<Note> found {conf_path} file, critical value will change !!!\033[m")
cp = ConfigParser()
cp.read(conf_path)
with PSP() as psp:
psp.lib.LMB_HWM_GetSensorType(byref(self._dw_sensor_type))
if self._dw_sensor_type.value == HWM_TYPE_NONE:
print("\033[1;31m<Warning> Hardware Monitor Type is Unknown !!!\033[m")
return
elif self._dw_sensor_type.value == HWM_TYPE_IPMI:
show_ipmi_only = True
print("\033[1;34m===> Hardware Monitor Type is IPMI <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_AST1400:
print("\033[1;34m===> Hardware Monitor Type is AST-1400 <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_SMBUS:
print("\033[1;34m===> Hardware Monitor Type is SMBus <===\033[m")
elif self._dw_sensor_type.value == HWM_TYPE_SIO:
print("\033[1;34m===> Hardware Monitor Type is SuperIO <===\033[m")
else:
print("\033[1;31m<Warning> Hardware Monitor Type is Unknown !!!\033[m")
return
print("Sensor Name Value LowCritical UpperCritical Result")
print("-------------------------------------------------------------------------")
# CPU Temperature
sid = HWMSensorItemV30.HWMID_TEMP_CPU1.value
for i in range(sid, sid + 4):
self._show_temperature_v30(i, cp)
# SYS Temperature
sid = HWMSensorItemV30.HWMID_TEMP_SYS1.value
for i in range(sid, sid + 4):
self._show_temperature_v30(i, cp)
# PCH Temperature
sid = HWMSensorItemV30.HWMID_TEMP_PCH.value
self._show_temperature_v30(sid, cp)
# CPU DIMM Temperature
sid = HWMSensorItemV30.HWMID_TEMP_DIMMP1A0.value
for i in range(sid, sid + 32):
self._show_temperature_v30(i, cp)
# CPU Vcore
sid = HWMSensorItemV30.HWMID_VCORE_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v30(i, cp)
# P12V
sid = HWMSensorItemV30.HWMID_VOLT_P12V.value
self._show_voltage_v30(sid, cp)
# P5V
sid = HWMSensorItemV30.HWMID_VOLT_P5V.value
self._show_voltage_v30(sid, cp)
# P3.3V
sid = HWMSensorItemV30.HWMID_VOLT_P3V3.value
self._show_voltage_v30(sid, cp)
# P5VSB
sid = HWMSensorItemV30.HWMID_VOLT_P5VSB.value
self._show_voltage_v30(sid, cp)
# P3.3VSB
sid = HWMSensorItemV30.HWMID_VOLT_P3V3SB.value
self._show_voltage_v30(sid, cp)
# VBAT
sid = HWMSensorItemV30.HWMID_VOLT_VBAT.value
self._show_voltage_v30(sid, cp)
# 1.05V
sid = HWMSensorItemV30.HWMID_VOLT_P1V05.value
self._show_voltage_v30(sid, cp)
# VCCIO
sid = HWMSensorItemV30.HWMID_VOLT_PVCCIO_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v30(i, cp)
# VCCSA
sid = HWMSensorItemV30.HWMID_VOLT_PVCCSA_CPU1.value
for i in range(sid, sid + 4):
self._show_voltage_v30(i, cp)
# VNN
sid = HWMSensorItemV30.HWMID_VOLT_PVNN.value
self._show_voltage_v30(sid, cp)
# DDR Voltage
sid = HWMSensorItemV30.HWMID_VOLT_DDRCH1.value
for i in range(sid, sid + 8):
self._show_voltage_v30(i, cp)
# extern sensors
sid = HWMSensorItemV30.HWMID_PSU2_TEMP2.value + 1
for i in range(sid, HWMSensorItemV30.HWMID_TOTAL.value):
self._show_voltage_v30(i, cp)
sid = HWMSensorItemV30.HWMID_RPM_Fan1A.value
for i in range(10):
self._show_rpm_v30(i * 2 + sid, cp)
self._show_rpm_v30(i * 2 + sid + 1, cp)
# IPMI PSU
for i in range(2):
if show_ipmi_only:
print("\033[2;31m================ For PSU when BMC exist ==========================\033[m")
show_ipmi_only = False
# PSU VIn
sid = HWMSensorItemV30.HWMID_PSU1_VOLTIN.value + 11 * i
self._show_voltage_v30(sid, cp)
# PSU Vout
sid = HWMSensorItemV30.HWMID_PSU1_VOLTOUT.value + 11 * i
self._show_voltage_v30(sid, cp)
# PSU Current In
sid = HWMSensorItemV30.HWMID_PSU1_CURRENTIN.value + 11 * i
self._show_current_v30(sid, cp)
# PSU Current Out
sid = HWMSensorItemV30.HWMID_PSU1_CURRENTOUT.value + 11 * i
self._show_current_v30(sid, cp)
# PSU Power In
sid = HWMSensorItemV30.HWMID_PSU1_POWERIN.value + 11 * i
self._show_watts_v30(sid, cp)
# PSU Power Out
sid = HWMSensorItemV30.HWMID_PSU1_POWEROUT.value + 11 * i
self._show_watts_v30(sid, cp)
# PSU Fan 1
sid = HWMSensorItemV30.HWMID_PSU1_FAN1.value + 11 * i
self._show_rpm_v30(sid, cp)
# PSU Fan 2
sid = HWMSensorItemV30.HWMID_PSU1_FAN2.value + 11 * i
self._show_rpm_v30(sid, cp)
# PSU Temp 1
sid = HWMSensorItemV30.HWMID_PSU1_TEMP1.value + 11 * i
self._show_temperature_v30(sid, cp)
# PSU Temp 2
sid = HWMSensorItemV30.HWMID_PSU1_TEMP2.value + 11 * i
self._show_temperature_v30(sid, cp)
def _show_temperature_v30(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '3.0.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
dw_lo_critical = c_int32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg)) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp, sizeof(str_disp))
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(dw_lo_critical), byref(udw_hi_critical))
min_ = dw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
temp = self._atoll(str_msg.value.decode()) / 1000
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = --N/A-- C, max = {int(max_):7d} C)", end="")
if temp > max_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = {int(min_):7d} C, max = --N/A-- C)", end="")
if temp < min_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = --N/A-- C, max = --N/A-- C)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(temp):7d} C\t"
f"(min = {int(min_):7d} C, max = {int(max_):7d} C)", end="")
if temp < min_ or temp > max_:
print(f" {ALARM}", end="")
print()
def _show_rpm_v30(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '3.0.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
dw_lo_critical = c_int32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg)) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp, sizeof(str_disp))
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(dw_lo_critical), byref(udw_hi_critical))
min_ = dw_lo_critical.value
max_ = udw_hi_critical.value
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
rpm = self._atoll(str_msg.value.decode())
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = --N/A-- rpm, max = {int(max_):5d} rpm)", end="")
if rpm > max_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = {int(min_):5d} rpm, max = --N/A-- rpm)", end="")
if rpm < min_:
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = --N/A-- rpm, max = --N/A-- rpm)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {int(rpm):5d} rpm\t"
f"(min = {int(min_):5d} rpm, max = {int(max_):5d} rpm)", end="")
if rpm < min_ or rpm > max_:
print(f" {ALARM}", end="")
print()
def _show_voltage_v30(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '3.0.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
dw_lo_critical = c_int32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg)) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp, sizeof(str_disp))
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(dw_lo_critical), byref(udw_hi_critical))
min_ = dw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
volt = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(volt * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = --N/A-- V, max = {max_:7.3f} V)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = {min_:7.3f} V, max = --N/A-- V)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = --N/A-- V, max = --N/A-- V)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} V\t"
f"(min = {min_:7.3f} V, max = {max_:7.3f} V)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
def _show_current_v30(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '3.0.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
dw_lo_critical = c_int32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg)) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp, sizeof(str_disp))
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(dw_lo_critical), byref(udw_hi_critical))
min_ = dw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
current = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(current * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = --N/A-- A, max = {max_:7.3f} A)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = {min_:7.3f} A, max = --N/A-- A)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = --N/A-- A, max = --N/A-- A)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} A\t"
f"(min = {min_:7.3f} A, max = {max_:7.3f} A)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
def _show_watts_v30(self, sid: int, cp: ConfigParser) -> None:
"""
For PSP version == '3.0.X'.
"""
str_msg = create_string_buffer(30)
str_disp = create_string_buffer(30)
str_id_name = create_string_buffer(30)
stu_sensor_info = IPMISensorInfo()
udw_hi_critical = c_uint32()
dw_lo_critical = c_int32()
f_flag_value = 0
memset(str_msg, 0, 30)
with PSP() as psp:
if psp.lib.LMB_HWM_GetSensorReport(sid, str_msg, sizeof(str_msg)) != ERR_NotSupport:
psp.lib.LMB_HWM_GetSensorDisplay(sid, str_disp, sizeof(str_disp))
psp.lib.LMB_HWM_GetSensorName(sid, str_id_name, sizeof(str_id_name))
min_ = self._str_replace(cp.get(str_id_name.value.decode(), "min", fallback="999999"))
if min_ == 999999: # hwm.conf not setting, read from SDK.
if self._dw_sensor_type.value == HWM_TYPE_IPMI:
i_ret = psp.lib.LMB_IPMI_InfoByName(str_disp, byref(stu_sensor_info))
if i_ret == ERR_Success:
min_ = stu_sensor_info.f_lo_critical
max_ = stu_sensor_info.f_hi_critical
else:
min_ = max_ = 0.0
else: # read from hwm_table.h
psp.lib.LMB_HWM_GetSensorCritical(sid, byref(dw_lo_critical), byref(udw_hi_critical))
min_ = dw_lo_critical.value / 1000
max_ = udw_hi_critical.value / 1000
else:
max_ = self._str_replace(cp.get(str_id_name.value.decode(), "max", fallback="999999"))
if min_ in (99999, 999999):
f_flag_value |= 0x01
if max_ in (99999, 999999):
f_flag_value |= 0x02
space_len = self._calc_space_string(str_disp.value.decode())
watts = self._atoll(str_msg.value.decode()) / 1000
round_up_buffer = int(watts * 1000)
if f_flag_value == 0x01: # min_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = --N/A-- W, max = {max_:7.3f} W)", end="")
if round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x02: # max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = {min_:7.3f} W, max = --N/A-- W)", end="")
if round_up_buffer < int(min_ * 1000):
print(f" {ALARM}", end="")
elif f_flag_value == 0x03: # min_ = N/A and max_ = N/A
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = --N/A-- W, max = --N/A-- W)", end="")
else:
print(f"{str_disp.value.decode()}{' ' * space_len} = {round_up_buffer * 0.001:7.3f} W\t"
f"(min = {min_:7.3f} W, max = {max_:7.3f} W)", end="")
if round_up_buffer < int(min_ * 1000) or round_up_buffer > int(max_ * 1000):
print(f" {ALARM}", end="")
print()
@classmethod
def _str_replace(cls, s: str) -> float:
"""Replace str to float from `hwm.conf`."""
result = 1.0
for element in s.split("*"):
result *= float(element.strip())
return result
@classmethod
def _atoll(cls, s: str) -> int:
pattern = r"[\s]*[+-]?[\d]+"
is_matched = match(pattern, s)
if is_matched:
result = int(is_matched.group(0))
if result > 2 ** 31 - 1:
result = 2 ** 31 - 1
if result < -2 ** 31:
result = -2 ** 31
else:
result = 0
return result
@classmethod
def _calc_space_string(cls, s: str) -> int:
max_len = 16
if len(s) <= max_len:
return max_len - len(s)
else:
return 0