Description
VNish.set_power_limit() (and more generally any code relying on MinerConfig.from_vnish().mining_mode being a MiningModePreset) never works for VNish firmware in preset/overclock mode, because MiningModeConfig.from_vnish() never actually returns a MiningModePreset instance — it always falls back to MiningModeNormal.
Root cause
In pyasic/config/mining/__init__.py:
@classmethod
def from_vnish(
cls, web_settings: dict, web_presets: list[dict], web_perf_summary: dict
) -> MiningModeConfig:
try:
mode_settings = web_settings["miner"]["overclock"]
except KeyError:
return cls.default()
if mode_settings["preset"] == "disabled":
return cls.manual.from_vnish(mode_settings, web_presets, web_perf_summary)
else:
return cls.preset.from_vnish(mode_settings, web_presets, web_perf_summary)
MiningModeConfig is an Enum (subclass of MinerConfigOption), and cls.preset / cls.manual are enum members whose .value is the actual config class (MiningModePreset / MiningModeManual). They are not the classes themselves.
Because from_vnish is defined as a @classmethod on MiningModeConfig, accessing .from_vnish on an enum member resolves back to MiningModeConfig.from_vnish (bound to MiningModeConfig, not to MiningModePreset/MiningModeManual). So cls.preset.from_vnish(mode_settings, web_presets, web_perf_summary) actually calls MiningModeConfig.from_vnish(mode_settings, web_presets, web_perf_summary) recursively, this time with mode_settings (the overclock dict) passed as web_settings.
Inside that recursive call, web_settings["miner"] (i.e. mode_settings["miner"]) raises KeyError (the overclock dict has no "miner" key), which is caught and returns cls.default() → MiningModeNormal().
Net effect: MiningModeConfig.from_vnish() always returns MiningModeNormal for VNish miners in preset mode (and likely also in manual/"disabled" mode, same bug via cls.manual.from_vnish).
Impact
VNishFirmware/VNish.set_power_limit() does:
if not isinstance(config.mining_mode, MiningModePreset):
return False
This is always True (mining_mode is always MiningModeNormal), so set_power_limit() always returns False, regardless of whether any presets are tuned. Any downstream caller that treats False as failure (e.g. Home Assistant's miner integration number.antminer_power_limit) raises an error (Failed to set wattage.) on every attempt, on every VNish miner.
Reproduction
miner = await get_miner("<vnish-ip>")
config = await miner.get_config()
print(type(config.mining_mode)) # always <class 'pyasic.config.mining.MiningModeNormal'>
result = await miner.set_power_limit(2050) # any wattage
print(result) # always False
Suggested fix
Use .value to get the actual class before calling from_vnish:
if mode_settings["preset"] == "disabled":
return cls.manual.value.from_vnish(mode_settings, web_presets, web_perf_summary)
else:
return cls.preset.value.from_vnish(mode_settings, web_presets, web_perf_summary)
I verified locally that MiningModeConfig.preset.value.from_vnish(mode_settings, web_presets, web_perf_summary) correctly returns a MiningModePreset instance with available_presets populated and tuned/power parsed correctly, and that set_power_limit() then behaves as intended.
Environment
- pyasic 0.79.0 (also present on
master)
- Miner: Antminer S19k Pro running VNish firmware
- Python 3.14
Description
VNish.set_power_limit()(and more generally any code relying onMinerConfig.from_vnish().mining_modebeing aMiningModePreset) never works for VNish firmware in preset/overclock mode, becauseMiningModeConfig.from_vnish()never actually returns aMiningModePresetinstance — it always falls back toMiningModeNormal.Root cause
In
pyasic/config/mining/__init__.py:MiningModeConfigis anEnum(subclass ofMinerConfigOption), andcls.preset/cls.manualare enum members whose.valueis the actual config class (MiningModePreset/MiningModeManual). They are not the classes themselves.Because
from_vnishis defined as a@classmethodonMiningModeConfig, accessing.from_vnishon an enum member resolves back toMiningModeConfig.from_vnish(bound toMiningModeConfig, not toMiningModePreset/MiningModeManual). Socls.preset.from_vnish(mode_settings, web_presets, web_perf_summary)actually callsMiningModeConfig.from_vnish(mode_settings, web_presets, web_perf_summary)recursively, this time withmode_settings(theoverclockdict) passed asweb_settings.Inside that recursive call,
web_settings["miner"](i.e.mode_settings["miner"]) raisesKeyError(theoverclockdict has no"miner"key), which is caught and returnscls.default()→MiningModeNormal().Net effect:
MiningModeConfig.from_vnish()always returnsMiningModeNormalfor VNish miners in preset mode (and likely also in manual/"disabled"mode, same bug viacls.manual.from_vnish).Impact
VNishFirmware/VNish.set_power_limit()does:This is always
True(mining_mode is alwaysMiningModeNormal), soset_power_limit()always returnsFalse, regardless of whether any presets are tuned. Any downstream caller that treatsFalseas failure (e.g. Home Assistant'sminerintegrationnumber.antminer_power_limit) raises an error (Failed to set wattage.) on every attempt, on every VNish miner.Reproduction
Suggested fix
Use
.valueto get the actual class before callingfrom_vnish:I verified locally that
MiningModeConfig.preset.value.from_vnish(mode_settings, web_presets, web_perf_summary)correctly returns aMiningModePresetinstance withavailable_presetspopulated andtuned/powerparsed correctly, and thatset_power_limit()then behaves as intended.Environment
master)