Controllare la temperatura dell'hardware mediante le funzioni del API di libsensors

Da Gambas-it.org - Wikipedia.

La libreria Libsensors mette a disposizione risorse per poter effettuare controlli su alcune parti ed aspetti dell'hardware per Linux. In particolare, ad esempio, questa libreria consente di gestire e visualizzare i dati del sensore della temperatura dell'hardware principale.

In un dato sistema, ci possono essere uno o più chip di controllo hardware. I nomi delle funzioni sono standardizzati. Ogni funzione può a sua volta avere uno o più sub-caratteristiche , ognuna di esse rappresenta un attributo della funzione: valore di ingresso , limite inferiore , limite superiore, limite di allarme, ecc. I nomi delle sub-funzionalità sono anch'essi predefiniti. Le sub-caratteristiche effettivamente esistenti dipendono dal tipo di chip presente nel sistema hardware.

La descrizione chip, restituita dall'apposita funzione esterna sensors_snprintf_chip_name(), è formata da più elementi, separati da trattini. Il primo elemento è il tipo di chip, il secondo elemento è il nome del bus, e il terzo elemento è l'indirizzo esadecimale del chip.

Riguardo alla configurazione della temperatura dei chip essa può avere due specifici sub-caratteristiche:

  • tipo di sensore di temperatura (tempX_type);
  • valori di isteresi (tempX_max_hyst e tempX_crit_hyst).

I tipi di sensori termici disponibili sono:
1 PII/Celeron Diode
2 3904 transistor
3 thermal diode
4 thermistor
5 AMD AMDSI
6 Intel PECI

L'Isteresi è la capacità di molti chip di far scattare un allarme quando la temperatura supera il suo limite massimo e critico previsto per quel chip, e di far cessare l'allarme quando la temperatura scende al di sotto di quel limite critico. Quindi , oltre a tempX_max, molti chip hanno una caratteristica secondaria: tempX_max_hyst e tempX_crit_hyst.


Per poter fruire delle risorse esterne della libreria libsensors, si dovrà richiamare l'attuale libreria: libsensors.so.4.3.2 .


Esempio pratico

Di seguito mostriamo un semplice, breve ed essenziale esempio di codice per monitorare la temperatura dell'hardware:

Library "libsensors:4.3.2"
 
Public Struct sensors_bus_id
  type As Short
  nr As Short
End Struct

Public Struct sensors_chip_name
  prefix As Pointer
  bus As Struct Sensors_bus_id
  addr As Integer
  path As Pointer
End Struct

Public Struct sensors_feature
  name As Pointer
  number As Integer
  type As Integer
  first_subfeature As Integer   ' Questi ultimi due campi servono soltanto per un uso interno alla libreria "libsensors"
  padding1 As Integer
End Struct

Public Struct sensors_subfeature
  name As Pointer
  number As Integer
  type As Integer
  mapping As Integer
  flags As Integer
End Struct

Private Const SENSORS_MODE_R As Byte = 1

' int sensors_init(FILE *input)
' Load the configuration file and the detected chips list. If this returns a value unequal to zero, you are in trouble
Private Extern sensors_init(filename As File) As Integer

' const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name *match, int *nr)
' This function returns all detected chips that match a given chip name, one by one. If no chip name is provided, all detected chips are returned.
Private Extern sensors_get_detected_chips(scnMatch As Pointer, nrP As Pointer) As Sensors_chip_name

' const sensors_feature * sensors_get_features(const sensors_chip_name *name, int *nr)
' This returns all main features of a specific chip. nr is an internally used variable. Set it to zero to start at the begin of the list. If no more features are found NULL is returned.
Private Extern sensors_get_features(chip_name As Sensors_chip_name, nrP As Pointer) As Sensors_feature

' const sensors_subfeature * sensors_get_all_subfeatures(const sensors_chip_name *name, const sensors_feature *feature, int *nr)
' This returns all subfeatures of a given main feature. nr is an internally used variable. Set it to zero to start at the begin of the list. If no more features are found NULL is returned.
Private Extern sensors_get_all_subfeatures(chip_name As Sensors_chip_name, feature As Sensors_feature, nrP As Pointer) As Sensors_subfeature

' int sensors_get_value(const sensors_chip_name *name, int subfeat_nr, double *value)
' Read the value of a subfeature of a certain chip. his function will return 0 on success, and <0 on failure.
Private Extern sensors_get_value(chip_name As Sensors_chip_name, subfeat_nr As Integer, value As Pointer) As Integer

' int sensors_snprintf_chip_name(char *str, size_t size, const sensors_chip_name *chip)
' Prints a chip name from its internal representation. Return the number of characters printed on success (same as snprintf), <0 on error.
Private Extern sensors_snprintf_chip_name(strp As Pointer, size As Integer, chip As Sensors_chip_name) As Integer

' const char* sensors_get_adapter_name (const sensors_bus_id * bus)
' Returns the adapter name of a bus number, as used within the sensors_chip_name structure. If it could not be found, it returns NULL.
Private Extern sensors_get_adapter_name(bus_id As Sensors_bus_id) As String

' void sensors_cleanup(void)
' Cleans everything up: you can't access anything after this, until the next sensors_init() call!
Private Extern sensors_cleanup()


Public Sub Main()

 Dim scnm As Sensors_chip_name
 Dim sf As Sensors_feature
 Dim subf As Sensors_subfeature
 Dim nomeB As New Byte[128]
 Dim c, lung, f, s, rc As Integer
 Dim valTemp As Float
  
  If sensors_init(Null) <> 0 Then Error.Raise("Impossibile inizializzare la libreria 'libsensors' !")
  
  scnm = sensors_get_detected_chips(0, VarPtr(c))

  lung = sensors_snprintf_chip_name(nomeB.Data, 128, scnm)
  Print nomeB.ToString(0, lung)
 
  Print "Adapter: "; sensors_get_adapter_name(scnm.bus)
   
  sf = sensors_get_features(scnm, VarPtr(f))
   
  Print "Tipo di sensore termico: "; sf_type(sf.type)
  Print

  subf = sensors_get_all_subfeatures(scnm, sf, VarPtr(s))
  If subf.flags And SENSORS_MODE_R Then 
    rc = sensors_get_value(scnm, subf.number, VarPtr(valTemp))
    If rc < 0 Then
      Error.Raise("Errore nella lettura del valore !")
    Else
      Print String@(sf.name); " = "; valTemp; "°"
    Endif
  Endif
  
  Print ".........................................\n"
   
  scnm = sensors_get_detected_chips(0, VarPtr(c))
  
  lung = sensors_snprintf_chip_name(nomeB.Data, 128, scnm)
  Print nomeB.ToString(0, lung)
  Print "Adapter: "; sensors_get_adapter_name(scnm.bus)
  Print "Tipo di sensore termico: "; sf_type(sf.type)
  Print
  
  If subf.flags And SENSORS_MODE_R Then 
    rc = sensors_get_value(scnm, subf.number, VarPtr(valTemp))
    If rc < 0 Then
      Error.Raise("Errore nella lettura del valore !")
    Else
      Print "Temperatura CPU = "; valTemp; "°"
    Endif
  Endif
  
  Print "''''''''''''''''''''''''''''''''''''"
  
  ' Va in chiusura:
  sensors_cleanup()
  
End
 

Private Function sf_type(numero As Byte) As String

 Dim tipo As String
 
  Select Case numero
    Case 1
      tipo = "PII/Celeron Diode"
    Case 2
      tipo = "3904 transistor"
    Case 3
      tipo = "thermal diode"
    Case 4
      tipo = "thermistor"
    Case 5
      tipo = "AMD AMDSI"
    Case 6
      tipo = "Intel PECI"
  End Select
   
  Return tipo
  
End



Riferimenti

[1] La pagina del API di lm_sensors .

[2] La pagina relativa al file sensors.conf.