Files
compute-blade-agent/pkg/smartfanunit/emc2101/emc2101.go
T
Cedric Kienzler 70541d86ba feat(agent)!: add support for mTLS authentication in gRPC server (#54)
* refactor(fancontroller): improve fan controller validation logic and error handling for temperature steps

* refactor(agent): restructure gRPC server implementation by moving it to a new api package for better organization and maintainability

* feat(agent): implement gRPC server for managing compute blade agents and add graceful shutdown support
refactor(agent): restructure agent code by moving API logic to a dedicated file and improving error handling
fix(agent): update logging messages for clarity and consistency across the agent's operations
chore(agent): remove unused API code and consolidate event handling logic for better maintainability
style(agent): improve code formatting and organization for better readability and adherence to conventions

* feat(agent): add support for TLS configuration in gRPC server

* feat(api): add gRPC server authentication

* fix

* feat(config): add listen mode configuration to support tcp or unix sockets
feat(agent): implement listen mode in gRPC service to allow flexible socket types
feat(bladectl): enhance configuration loading and add support for TLS credentials
fix(bladectl): improve error handling for gRPC connection and event emission
style(logging): change log level from Warn to Info for better clarity in logs

* add logging middleware + fixes

* fix remote-connection to gRPC API Server

debugging the SAN issues took the soul out of me... And then the stupid
mistake in cmd_root where I didn't construct the TLS credentials
correctly... Oh dear...

* cleanup

* cleanup

* cleanup commands

* cleanup

* make README.md nicer

* Update cmd/agent/main.go

Co-authored-by: Matthias Riegler <github@m4tbit.de>

* Update cmd/bladectl/cmd_root.go

Co-authored-by: Matthias Riegler <github@m4tbit.de>

* move bladectl config into correct directory

* fix bugs

* // FIXME: No dead code

* nit: code style

* nit(YAGNI): you aint gonna need it. Don't make life harder than it needs to be

* nit(YAGNI): you aint gonna need it. Don't make life harder than it needs to be

* nit(YAGNI): you aint gonna need it. Don't make life harder than it needs to be

* nit(cmd_identify)

---------

Co-authored-by: Matthias Riegler <github@m4tbit.de>
2025-05-12 00:00:55 +02:00

132 lines
3.1 KiB
Go

// Package emc2101 is a driver for the EMC2101 fan controller
// Based on https://ww1.microchip.com/downloads/en/DeviceDoc/2101.pdf
package emc2101
import (
"tinygo.org/x/drivers"
)
type emc2101 struct {
Address uint16
bus drivers.I2C
}
// EMC2101 is a driver for the EMC2101 fan controller
type EMC2101 interface {
// Init initializes the EMC2101
Init() error
// InternalTemperature returns the internal temperature of the EMC2101
InternalTemperature() (float32, error)
// ExternalTemperature returns the external temperature of the EMC2101
ExternalTemperature() (float32, error)
// SetFanPercent sets the fan speed as a percentage of max
SetFanPercent(percent uint8) error
// FanRPM returns the current fan speed in RPM
FanRPM() (float32, error)
}
const (
// Address is the default I2C address for the EMC2101
Address = 0x4C
ConfigReg = 0x03
FanConfigReg = 0x4a
FanSpinUpReg = 0x4b
FanSettingReg = 0x4c
FanTachReadingLowReg = 0x46
FanTachReadingHighReg = 0x47
ExternalTempReg = 0x01
InternalTempReg = 0x00
)
func New(bus drivers.I2C) EMC2101 {
return &emc2101{bus: bus, Address: Address}
}
// updateReg updates a register with the given set and clear masks
func (e *emc2101) updateReg(regAddr, setMask, clearMask uint8) error {
buf := make([]uint8, 1)
err := e.bus.Tx(e.Address, []byte{regAddr}, buf)
if err != nil {
return err
}
toWrite := buf[0]
toWrite |= setMask
toWrite &= ^clearMask
if toWrite == buf[0] {
return nil
}
return e.bus.Tx(e.Address, []byte{regAddr, toWrite}, nil)
}
func (e *emc2101) Init() error {
// set pwm mode
// bit 4: 0 = PWM mode
// bit 2: 1 = TACH input
if err := e.updateReg(ConfigReg, (1 << 2), (1 << 4)); err != nil {
return err
}
if err := e.updateReg(FanConfigReg, (1 << 5), 0); err != nil {
return err
}
/*
0x3 0b100
0x4b 0b11111
0x4a 0b100000
0x4a 0b100000
*/
// Configure fan spin up to ignore tach input
// bit 5: 1 = Ignore tach input for spin up procedure
if err := e.updateReg(FanSpinUpReg, 0, (1 << 5)); err != nil {
return err
}
return nil
}
func (e *emc2101) InternalTemperature() (float32, error) {
buf := make([]byte, 1)
if err := e.bus.Tx(e.Address, []byte{InternalTempReg}, buf); err != nil {
return 0, err
}
return float32(buf[0]), nil
}
func (e *emc2101) ExternalTemperature() (float32, error) {
buf := make([]byte, 1)
if err := e.bus.Tx(e.Address, []byte{ExternalTempReg}, buf); err != nil {
return 0, err
}
return float32(buf[0]), nil
}
func (e *emc2101) SetFanPercent(percent uint8) error {
if percent > 100 {
percent = 100
}
val := uint8(uint32(percent) * 63 / 100)
return e.bus.Tx(e.Address, []byte{FanSettingReg, val}, nil)
}
func (e *emc2101) FanRPM() (float32, error) {
high := make([]byte, 1)
low := make([]byte, 1)
err := e.bus.Tx(e.Address, []byte{FanTachReadingHighReg}, high)
if err != nil {
return 0, err
}
err = e.bus.Tx(e.Address, []byte{FanTachReadingLowReg}, low)
if err != nil {
return 0, err
}
var tachCount = int(high[0])<<8 | int(low[0])
return float32(5400000) / float32(tachCount), nil
}