diff --git a/IoTuring/Entity/Deployments/Fanspeed/Fanspeed.py b/IoTuring/Entity/Deployments/Fanspeed/Fanspeed.py new file mode 100644 index 000000000..d208020c9 --- /dev/null +++ b/IoTuring/Entity/Deployments/Fanspeed/Fanspeed.py @@ -0,0 +1,95 @@ +import psutil +from IoTuring.Entity.Entity import Entity +from IoTuring.Entity.EntityData import EntitySensor +from IoTuring.Entity.ValueFormat import ValueFormatterOptions +from IoTuring.MyApp.SystemConsts import OperatingSystemDetection as OsD + + +VALUEFORMATTEROPTIONS_FANSPEED_RPM = ValueFormatterOptions( + value_type=ValueFormatterOptions.TYPE_ROTATION) + + +FALLBACK_CONTROLLER_LABEL = "controller" +FALLBACK_FAN_LABEL = "fan" + + +class Fanspeed(Entity): + """Entity to read fanspeed""" + NAME = "Fanspeed" + + def Initialize(self) -> None: + """Initialize the Class, setup Formatter, determin specificInitialize and specificUpdate depending on OS""" + + self.specificInitialize = None + self.specificUpdate = None + + if OsD.IsLinux(): + # psutil docs: no attribute -> system not supported + if not hasattr(psutil, "sensors_fans"): + raise Exception("System not supported by psutil") + # psutil docs: empty dict -> no fancontrollers reporting + if not bool(psutil.sensors_fans()): + raise Exception("No fan found in system") + self.specificInitialize = self.InitLinux + self.specificUpdate = self.UpdateLinux + + else: + raise NotImplementedError + + self.specificInitialize() + + def InitLinux(self) -> None: + """OS dependant Init for Linux""" + sensors = psutil.sensors_fans() + self.Log(self.LOG_DEBUG, f"fancontrollers found:{sensors}") + + for i, controller in enumerate(sensors): + # use FALLBACK for blank controllernames + controllerName = controller or FALLBACK_CONTROLLER_LABEL + str(i) + + # Add extra attributes only if there are multiple fans: + hasMultipleFans = bool(len(sensors[controller]) > 1) + + # register an entity for each controller + self.RegisterEntitySensor( + EntitySensor( + self, + controllerName, + supportsExtraAttributes=hasMultipleFans, + valueFormatterOptions=VALUEFORMATTEROPTIONS_FANSPEED_RPM, + ) + ) + + def Update(self) -> None: + """placeholder for OS specificUpdate""" + if self.specificUpdate: + self.specificUpdate() + else: + raise NotImplementedError + + def UpdateLinux(self) -> None: + """Updatemethod for Linux""" + for controller, fans in psutil.sensors_fans().items(): + # get all fanspeed in a list and find max + highest_fan = max([fan.current for fan in fans]) + # find higest fanspeed and assign the entity state + self.SetEntitySensorValue( + key=controller, + value=highest_fan) + # Set extra attributes {fan name : fanspeed in rpm} + self.Log(self.LOG_DEBUG, + f"updating controller:{controller} with {fans}") + + # Add fans as extra attributes, if there are more than one: + if len(fans) > 1: + for i, fan in enumerate(fans): + # appy FALLBACK if label is blank + fanlabel = fan.label or FALLBACK_FAN_LABEL + str(i) + + # set extra attributes for each fan + self.SetEntitySensorExtraAttribute( + controller, + fanlabel, + fan.current, + valueFormatterOptions=VALUEFORMATTEROPTIONS_FANSPEED_RPM, + ) diff --git a/IoTuring/Entity/ValueFormat/ValueFormatter.py b/IoTuring/Entity/ValueFormat/ValueFormatter.py index 75970928a..ec943069e 100644 --- a/IoTuring/Entity/ValueFormat/ValueFormatter.py +++ b/IoTuring/Entity/ValueFormat/ValueFormatter.py @@ -17,6 +17,7 @@ FREQUENCY_SIZES = ['Hz', 'kHz', 'MHz', 'GHz'] TIME_SIZES_DIVIDERS = [1, 60, 60, 24] CELSIUS_UNIT = '°C' +ROTATION = ['rpm'] SPACE_BEFORE_UNIT = ' ' @@ -50,6 +51,8 @@ def _ParseValue(value, options: ValueFormatterOptions | None, includeUnit: bool) return ValueFormatter.FrequencyFormatter(value, options, includeUnit) elif valueType == ValueFormatterOptions.TYPE_TEMPERATURE: return ValueFormatter.TemperatureCelsiusFormatter(value, options, includeUnit) + elif valueType == ValueFormatterOptions.TYPE_ROTATION: + return ValueFormatter.RoundsPerMinuteFormatter(value, options, includeUnit) elif valueType == ValueFormatterOptions.TYPE_PERCENTAGE: if includeUnit: return str(value) + SPACE_BEFORE_UNIT + '%' @@ -152,6 +155,19 @@ def TemperatureCelsiusFormatter(value, options: ValueFormatterOptions, includeUn result = result + SPACE_BEFORE_UNIT + CELSIUS_UNIT return result + @staticmethod + def RoundsPerMinuteFormatter(value, options: ValueFormatterOptions, includeUnit: bool): + # asked_size not implemented + + # decimals + value = ValueFormatter.roundValue(value, options) + + result = str(value) + + if includeUnit: + result = result + SPACE_BEFORE_UNIT + ROTATION[0] + return result + @staticmethod def roundValue(value, options: ValueFormatterOptions): if options.get_decimals() != ValueFormatterOptions.DO_NOT_TOUCH_DECIMALS: diff --git a/IoTuring/Entity/ValueFormat/ValueFormatterOptions.py b/IoTuring/Entity/ValueFormat/ValueFormatterOptions.py index 7611c1ac3..3fc676ecb 100644 --- a/IoTuring/Entity/ValueFormat/ValueFormatterOptions.py +++ b/IoTuring/Entity/ValueFormat/ValueFormatterOptions.py @@ -6,6 +6,7 @@ class ValueFormatterOptions(): TYPE_FREQUENCY = 4 TYPE_MILLISECONDS = 5 TYPE_TEMPERATURE = 6 + TYPE_ROTATION = 7 DO_NOT_TOUCH_DECIMALS = -1 diff --git a/IoTuring/Warehouse/Deployments/HomeAssistantWarehouse/entities.yaml b/IoTuring/Warehouse/Deployments/HomeAssistantWarehouse/entities.yaml index 518b8028c..c5afe11e0 100644 --- a/IoTuring/Warehouse/Deployments/HomeAssistantWarehouse/entities.yaml +++ b/IoTuring/Warehouse/Deployments/HomeAssistantWarehouse/entities.yaml @@ -77,6 +77,9 @@ AppInfo: Temperature: icon: mdi:thermometer-lines unit_of_measurement: °C +Fanspeed: + icon: mdi:fan + unit_of_measurement: rpm DisplayMode: name: Display Mode icon: mdi:monitor-multiple diff --git a/README.md b/README.md index 0ba876e98..1b04868d2 100644 --- a/README.md +++ b/README.md @@ -138,8 +138,8 @@ All sensors and switches will be available to be added to your dashboard in your ### Available entities -| Name | Description | Supported platforms | -| ------------------ | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| Name | Description | Supported platforms | +| ------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ActiveWindow | shares the name of the window you're working on | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | AppInfo | shares app informations like the running version | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Battery | shares the battery level and charging status | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | @@ -147,20 +147,21 @@ All sensors and switches will be available to be added to your dashboard in your | Cpu | shares useful information about cpu usage (times, frequencies, percentages) | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | DesktopEnvironment | shares the running desktop environment (useful only for Linux) | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Disk | shares disk usage data | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | -| DisplayMode | command for changing multimonitor display mode | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) | +| DisplayMode | command for changing multimonitor display mode | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) | +| Fanspeed | shares maximum fanspeed of each controller | ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Hostname | shares the machine hostname | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Lock | command for locking the machine | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | -| Monitor | command for switching monitors on/off | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | +| Monitor | command for switching monitors on/off | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Notify | displays a notification | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | OperatingSystem | shares the operating system of your machine | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Power* | commands for poweroff, reboot and sleep | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Ram | shares useful information about ram usage | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | -| Time | shares the machine local time | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | -| Temperature | shares temperature sensor data | ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | +| Temperature | shares temperature sensor data | ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Terminal | runs custom commands in the shell | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | +| Time | shares the machine local time | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Uptime | shares the time since the machine is on | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | | Username | shares the name of the user who is working on the machine | ![win](https://github.com/richibrics/IoTuring/blob/main/docs/images/win.png?raw=true) ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | -| Volume | control audio volume | ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | +| Volume | control audio volume | ![mac](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/mac.png) ![linux](https://raw.githubusercontent.com/richibrics/IoTuring/main/docs/images/linux.png) | \* To use the features from Power entity on macOS and on some Linux distros you need to give permissions to your user to shutdown and reboot without sudo password.