Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyasic/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class MinerData(BaseModel):
api_ver: The current api version on the miner as a str.
fw_ver: The current firmware version on the miner as a str.
hostname: The network hostname of the miner as a str.
psu_serial_number: The serial number of the PSU if provided by the miner.
hashrate: The hashrate of the miner in TH/s as a float. Calculated automatically.
expected_hashrate: The factory nominal hashrate of the miner in TH/s as a float.
sticker_hashrate: The factory sticker hashrate of the miner as a float.
Expand Down Expand Up @@ -86,6 +87,7 @@ class MinerData(BaseModel):
# about
device_info: DeviceInfo | None = None
serial_number: str | None = None
psu_serial_number: str | None = None
mac: str | None = None
api_ver: str | None = None
fw_ver: str | None = None
Expand Down
38 changes: 38 additions & 0 deletions pyasic/miners/backends/braiins_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,14 @@ async def upgrade_firmware(

BOSER_DATA_LOC = DataLocations(
**{
str(DataOptions.SERIAL_NUMBER): DataFunction(
"_get_serial_number",
[WebAPICommand("grpc_miner_details", "get_miner_details")],
),
str(DataOptions.PSU_SERIAL_NUMBER): DataFunction(
"_get_psu_serial_number",
[WebAPICommand("grpc_miner_details", "get_miner_details")],
),
str(DataOptions.MAC): DataFunction(
"_get_mac",
[WebAPICommand("grpc_miner_details", "get_miner_details")],
Expand Down Expand Up @@ -929,6 +937,34 @@ async def _get_hostname(self, grpc_miner_details: dict | None = None) -> str | N
pass
return None

async def _get_serial_number(
self, grpc_miner_details: dict | None = None
) -> str | None:
if grpc_miner_details is None:
try:
grpc_miner_details = await self.web.get_miner_details()
except APIError:
return None

if grpc_miner_details is not None:
return grpc_miner_details.get("serialNumber")
return None

async def _get_psu_serial_number(
self, grpc_miner_details: dict | None = None
) -> str | None:
if grpc_miner_details is None:
try:
grpc_miner_details = await self.web.get_miner_details()
except APIError:
return None

if grpc_miner_details is not None:
psu_info = grpc_miner_details.get("psuInfo")
if psu_info:
return psu_info.get("serialNumber")
return None

async def _get_hashrate(
self, rpc_summary: dict | None = None
) -> AlgoHashRateType | None:
Expand Down Expand Up @@ -1011,6 +1047,8 @@ async def _get_hashboards(
).into(
self.algo.unit.default # type: ignore[attr-defined]
)
if board.get("serialNumber") is not None:
hashboards[idx].serial_number = board["serialNumber"]
hashboards[idx].missing = False

return hashboards
Expand Down
11 changes: 11 additions & 0 deletions pyasic/miners/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ async def get_serial_number(self) -> str | None:
"""
return await self._get_serial_number()

async def get_psu_serial_number(self) -> str | None:
"""Get the PSU serial number reported by the miner.

Returns:
A string representing the PSU serial number of the miner.
"""
return await self._get_psu_serial_number()

async def get_mac(self) -> str | None:
"""Get the MAC address of the miner and return it as a string.

Expand Down Expand Up @@ -392,6 +400,9 @@ async def get_pools(self) -> list[PoolMetrics]:
async def _get_serial_number(self) -> str | None:
pass

async def _get_psu_serial_number(self) -> str | None:
return None

async def _get_mac(self) -> str | None:
return None

Expand Down
1 change: 1 addition & 0 deletions pyasic/miners/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

class DataOptions(Enum):
SERIAL_NUMBER = "serial_number"
PSU_SERIAL_NUMBER = "psu_serial_number"
MAC = "mac"
API_VERSION = "api_ver"
FW_VERSION = "fw_ver"
Expand Down
64 changes: 64 additions & 0 deletions pyasic/web/braiins_os/proto/braiins/bos/v1/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions tests/local_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!-- markdownlint-disable MD043 -->
# Lokales Testen mit einem echten Braiins OS Miner

Dieses Verzeichnis enthält Test-Skripte für manuelle Tests mit
echter Hardware (Braiins OS Miner).

## 📋 Dateien

- **test_braiins_serials.py** - Test-Skript für Serial Numbers
- **README.md** - Diese Dokumentation

## 🚀 Schnellanleitung

### Mit Standard-Zugangsdaten (root/root)

```bash
cd /workspaces/pyasic
python tests/local_tests/test_braiins_serials.py 192.168.1.100
```

### Mit benutzerdefinierten Zugangsdaten

```bash
python tests/local_tests/test_braiins_serials.py 192.168.1.100 \
admin meinpasswort
```

## ✅ Was wird getestet

Das Skript `test_braiins_serials.py` prüft:

1. **Miner-Verbindung**: Automatische Typ-Erkennung
2. **Miner Serial Number** (`get_serial_number()`)
- Ruft die Seriennummer des Miners ab
- Verfügbar ab Firmware 25.03

3. **PSU Serial Number** (`get_psu_serial_number()`)
- Ruft die Seriennummer des Power Supply Units ab
- Verfügbar ab Firmware 25.03

4. **Hashboard Serial Numbers**
- Seriennummern aller Hashboards
- Details pro Hashboard (Slot, Chips, Temperatur)

5. **Zusatzdaten**
- IP, MAC Address
- Firmware Version, API Version

## 📋 Voraussetzungen

- Python 3.8+
- Braiins OS Plus Miner mit Firmware 25.03 oder neuer
- Netzwerkzugriff zum Miner
- Miner-IP-Adresse und Zugangsdaten (Standard: root/root)

## 💡 Hinweise

- **Für ältere Firmware**: Serial Numbers benötigen Firmware >= 25.03
- **Standard-Zugangsdaten**: Meist root/root als Standard
- **Netzwerk**: SSH (Port 22) und gRPC (Port 50051) erforderlich
- **Timeout**: Bis zu 30 Sekunden je nach Miner-Auslastung

## 🔧 Debuggen bei Fehlern

Falls das Skript Fehler meldet:

1. **Verbindungsfehler**: IP-Adresse und Netzwerk überprüfen
2. **Authentifizierung fehlgeschlagen**: Username/Passwort prüfen
3. **Firmware zu alt**: Firmware-Version prüfen (mind. 25.03)
4. **Service nicht erreichbar**: Miner-Status überprüfen

## 📚 Weitere Informationen

Die neuen Features sind implementiert in:

- `pyasic/miners/backends/braiins_os.py` (BOSer-Backend)
- `pyasic/miners/base.py` (Basis-Interface)
- `pyasic/data/__init__.py` (Datenmodell)

Siehe GitHub PR #402 für vollständige Details.
6 changes: 6 additions & 0 deletions tests/local_tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Local manual tests for hardware testing.

This module contains test scripts for manual testing with real hardware.
These tests require actual ASIC miners on the network and are not part of
the automated test suite.
"""
Loading