diff --git a/main/http_server/axe-os/src/app/app.module.ts b/main/http_server/axe-os/src/app/app.module.ts index 922a8a293..c753f4b0b 100644 --- a/main/http_server/axe-os/src/app/app.module.ts +++ b/main/http_server/axe-os/src/app/app.module.ts @@ -28,6 +28,7 @@ import { AppLayoutModule } from './layout/app.layout.module'; import { ANSIPipe } from './pipes/ansi.pipe'; import { DateAgoPipe } from './pipes/date-ago.pipe'; import { HashSuffixPipe } from './pipes/hash-suffix.pipe'; +import { DiffSuffixPipe } from './pipes/diff-suffix.pipe'; import { PrimeNGModule } from './prime-ng.module'; import { MessageModule } from 'primeng/message'; import { TooltipModule } from 'primeng/tooltip'; @@ -59,6 +60,7 @@ const components = [ SwarmComponent, SettingsComponent, HashSuffixPipe, + DiffSuffixPipe, ThemeConfigComponent, DesignComponent, PoolComponent, diff --git a/main/http_server/axe-os/src/app/components/home/home.component.html b/main/http_server/axe-os/src/app/components/home/home.component.html index e77008939..424a0b5bb 100644 --- a/main/http_server/axe-os/src/app/components/home/home.component.html +++ b/main/http_server/axe-os/src/app/components/home/home.component.html @@ -126,12 +126,12 @@
Best Difficulty -
{{info.bestDiff}} +
{{info.bestDiff | diffSuffix}} all-time best
- {{info.bestSessionDiff}} + {{info.bestSessionDiff | diffSuffix}} since system boot
diff --git a/main/http_server/axe-os/src/app/components/home/home.component.ts b/main/http_server/axe-os/src/app/components/home/home.component.ts index 82885a0e5..ed2137be6 100644 --- a/main/http_server/axe-os/src/app/components/home/home.component.ts +++ b/main/http_server/axe-os/src/app/components/home/home.component.ts @@ -4,6 +4,7 @@ import { HttpErrorResponse } from '@angular/common/http'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; import { HashSuffixPipe } from 'src/app/pipes/hash-suffix.pipe'; +import { DiffSuffixPipe } from 'src/app/pipes/diff-suffix.pipe'; import { ByteSuffixPipe } from 'src/app/pipes/byte-suffix.pipe'; import { QuicklinkService } from 'src/app/services/quicklink.service'; import { ShareRejectionExplanationService } from 'src/app/services/share-rejection-explanation.service'; @@ -482,7 +483,7 @@ export class HomeComponent implements OnInit, OnDestroy { (info.hashRate ? HashSuffixPipe.transform(info.hashRate) : ''), (info.temp ? `${info.temp}${info.temp2 > -1 ? `/${info.temp2}` : ''}${info.vrTemp ? `/${info.vrTemp}` : ''} °C` : ''), (!info.power_fault ? `${info.power} W` : ''), - (info.bestDiff ? info.bestDiff : ''), + (info.bestDiff ? DiffSuffixPipe.transform(info.bestDiff) : ''), ); } diff --git a/main/http_server/axe-os/src/app/components/swarm/swarm.component.html b/main/http_server/axe-os/src/app/components/swarm/swarm.component.html index 03eeb0d8d..255202b3c 100644 --- a/main/http_server/axe-os/src/app/components/swarm/swarm.component.html +++ b/main/http_server/axe-os/src/app/components/swarm/swarm.component.html @@ -7,7 +7,7 @@

Swarm

{ label: 'Total Devices', value: swarm.length }, { label: 'Total Hashrate', value: totals.hashRate * 1000000000 | hashSuffix}, { label: 'Total Power', value: (totals.power | number: '1.1-1') + ' W' }, - { label: 'Best Diff', value: totals.bestDiff } + { label: 'Best Diff', value: totals.bestDiff | diffSuffix } ]">
{{metric.label}} @@ -150,10 +150,10 @@

Swarm

- {{axe.bestSessionDiff}} + {{axe.bestSessionDiff | diffSuffix}} - {{axe.bestDiff}} + {{axe.bestDiff | diffSuffix}}
@@ -224,10 +224,10 @@

Swarm

- {{axe.bestDiff}} + {{axe.bestDiff | diffSuffix}}

- {{axe.bestSessionDiff}} + {{axe.bestSessionDiff | diffSuffix}}

@@ -318,4 +318,4 @@

Swarm

-
+ \ No newline at end of file diff --git a/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts b/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts index 42becc516..d899fb4d3 100644 --- a/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts +++ b/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts @@ -6,6 +6,7 @@ import { forkJoin, catchError, from, map, mergeMap, of, take, timeout, toArray, import { LocalStorageService } from 'src/app/local-storage.service'; import { LayoutService } from "../../layout/service/app.layout.service"; import { ModalComponent } from '../modal/modal.component'; +import { ISystemInfo } from 'src/models/ISystemInfo'; const SWARM_DATA = 'SWARM_DATA'; const SWARM_REFRESH_TIME = 'SWARM_REFRESH_TIME'; @@ -35,7 +36,7 @@ export class SwarmComponent implements OnInit, OnDestroy { public refreshIntervalTime = 30; public refreshTimeSet = 30; - public totals: { hashRate: number; power: number; bestDiff: string } = { hashRate: 0, power: 0, bestDiff: '0' }; + public totals: { hashRate: number; power: number; bestDiff: number } = { hashRate: 0, power: 0, bestDiff: 0 }; public isRefreshing = false; @@ -163,12 +164,12 @@ export class SwarmComponent implements OnInit, OnDestroy { private getAllDeviceInfo(ips: string[], errorHandler: (error: any, ip: string) => Observable, fetchAsic: boolean = true) { return from(ips).pipe( mergeMap(IP => forkJoin({ - info: this.httpClient.get(`http://${IP}/api/system/info`), - asic: fetchAsic ? this.httpClient.get(`http://${IP}/api/system/asic`).pipe(catchError(() => of({}))) : of({}) + info: this.httpClient.get(`http://${IP}/api/system/info`), + asic: fetchAsic ? this.httpClient.get(`http://${IP}/api/system/asic`).pipe(catchError(() => of({}))) : of({}) }).pipe( map(({ info, asic }) => { const existingDevice = this.swarm.find(device => device.IP === IP); - const result = { IP, ...(existingDevice ? existingDevice : {}), ...info, ...asic }; + const result = { IP, ...(existingDevice ? existingDevice : {}), ...info, ...asic, ...this.numerizeDeviceBestDiffs(info) }; return this.fallbackDeviceModel(result); }), timeout(5000), @@ -197,7 +198,7 @@ export class SwarmComponent implements OnInit, OnDestroy { return; } - this.swarm.push({ IP, ...asic, ...info }); + this.swarm.push({ IP, ...asic, ...info, ...this.numerizeDeviceBestDiffs(info) }); this.sortSwarm(); this.localStorageService.setObject(SWARM_DATA, this.swarm); this.calculateTotals(); @@ -310,29 +311,10 @@ export class SwarmComponent implements OnInit, OnDestroy { }); } - private compareBestDiff(a: string, b: string): string { - if (!a || a === '0') return b || '0'; - if (!b || b === '0') return a; - - const units = 'kMGTPE'; - const unitA = units.indexOf(a.slice(-1)); - const unitB = units.indexOf(b.slice(-1)); - - if (unitA !== unitB) { - return unitA > unitB ? a : b; - } - - const valueA = parseFloat(a.slice(0, unitA >= 0 ? -1 : 0)); - const valueB = parseFloat(b.slice(0, unitB >= 0 ? -1 : 0)); - return valueA >= valueB ? a : b; - } - private calculateTotals() { this.totals.hashRate = this.swarm.reduce((sum, axe) => sum + (axe.hashRate || 0), 0); this.totals.power = this.swarm.reduce((sum, axe) => sum + (axe.power || 0), 0); - this.totals.bestDiff = this.swarm - .map(axe => axe.bestDiff || '0') - .reduce((max, curr) => this.compareBestDiff(max, curr), '0'); + this.totals.bestDiff = this.swarm.reduce((max, axe) => Math.max(max, axe.bestDiff || 0), 0); } get deviceFamilies(): SwarmDevice[] { @@ -378,6 +360,36 @@ export class SwarmComponent implements OnInit, OnDestroy { } } + private numerizeDeviceBestDiffs(info: ISystemInfo) { + const parseAsNumber = (val: number | string): number => { + return typeof val === 'string' ? this.parseSuffixString(val) : val; + }; + + return { + bestDiff: parseAsNumber(info.bestDiff), + bestSessionDiff: parseAsNumber(info.bestSessionDiff), + }; + } + + private parseSuffixString(input: string): number { + input = input.trim(); + const value = parseFloat(input); + const lastChar = input.charAt(input.length - 1).toUpperCase(); + + const multipliers: Record = { + K: 1e3, + M: 1e6, + G: 1e9, + T: 1e12, + P: 1e15, + E: 1e18, + }; + + const multiplier = multipliers[lastChar] ?? 1; + + return value * multiplier; + } + public stringifyDeviceLabel(data: any): string { const model = data.deviceModel || 'Other'; const asicCountPart = data.asicCount > 1 ? data.asicCount + 'x ' : ''; diff --git a/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.spec.ts b/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.spec.ts new file mode 100644 index 000000000..36393deca --- /dev/null +++ b/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DiffSuffixPipe } from './diff-suffix.pipe'; + +describe('DiffSuffixPipe', () => { + it('create an instance', () => { + const pipe = new DiffSuffixPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.ts b/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.ts new file mode 100644 index 000000000..7c191ad08 --- /dev/null +++ b/main/http_server/axe-os/src/app/pipes/diff-suffix.pipe.ts @@ -0,0 +1,33 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'diffSuffix', + pure: true +}) +export class DiffSuffixPipe implements PipeTransform { + + private static _this = new DiffSuffixPipe(); + + public static transform(value: number): string { + return this._this.transform(value); + } + + public transform(value: number): string { + if (value == null || value < 0) { + return '0'; + } + + const suffixes = ['', 'K', 'M', 'G', 'T', 'P', 'E']; + + const power = Math.max(0, Math.floor(Math.log10(value) / 3)); + const scaledValue = value / Math.pow(1000, power); + const suffix = suffixes[power] ?? ''; + const space = suffix ? ' ' : ''; + + if (power > 0) { + return scaledValue.toFixed(2) + space + suffix; + } else { + return scaledValue.toFixed(0) + space + suffix; + } + } +} diff --git a/main/http_server/axe-os/src/app/services/system.service.ts b/main/http_server/axe-os/src/app/services/system.service.ts index 644e6e1ae..f8569aa01 100644 --- a/main/http_server/axe-os/src/app/services/system.service.ts +++ b/main/http_server/axe-os/src/app/services/system.service.ts @@ -37,8 +37,8 @@ export class SystemService { nominalVoltage: 5, hashRate: 475, expectedHashrate: 420, - bestDiff: "0", - bestSessionDiff: "0", + bestDiff: 238214491, + bestSessionDiff: 21212121, freeHeap: 200504, freeHeapInternal: 200504, freeHeapSpiram: 200504, diff --git a/main/http_server/axe-os/src/models/ISystemInfo.ts b/main/http_server/axe-os/src/models/ISystemInfo.ts index b6e10a174..0848fb6d5 100644 --- a/main/http_server/axe-os/src/models/ISystemInfo.ts +++ b/main/http_server/axe-os/src/models/ISystemInfo.ts @@ -30,8 +30,8 @@ export interface ISystemInfo { nominalVoltage: number, hashRate: number, expectedHashrate: number, - bestDiff: string, - bestSessionDiff: string, + bestDiff: number, + bestSessionDiff: number, freeHeap: number, freeHeapInternal: number, freeHeapSpiram: number, diff --git a/main/http_server/http_server.c b/main/http_server/http_server.c index 6f8abaca1..bfbac0d6d 100644 --- a/main/http_server/http_server.c +++ b/main/http_server/http_server.c @@ -912,8 +912,8 @@ static esp_err_t GET_system_info(httpd_req_t * req) cJSON_AddNumberToObject(root, "hashrateRegister", GLOBAL_STATE->HASHRATE_MONITOR_MODULE.hashrate); cJSON_AddNumberToObject(root, "errorCountRegister", GLOBAL_STATE->HASHRATE_MONITOR_MODULE.error_count); cJSON_AddNumberToObject(root, "expectedHashrate", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.expected_hashrate); - cJSON_AddStringToObject(root, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_diff_string); - cJSON_AddStringToObject(root, "bestSessionDiff", GLOBAL_STATE->SYSTEM_MODULE.best_session_diff_string); + cJSON_AddNumberToObject(root, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_nonce_diff); + cJSON_AddNumberToObject(root, "bestSessionDiff", GLOBAL_STATE->SYSTEM_MODULE.best_session_nonce_diff); cJSON_AddNumberToObject(root, "poolDifficulty", GLOBAL_STATE->pool_difficulty); cJSON_AddNumberToObject(root, "isUsingFallbackStratum", GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback); diff --git a/main/http_server/openapi.yaml b/main/http_server/openapi.yaml index 9ec9e3c29..39fc54d0c 100644 --- a/main/http_server/openapi.yaml +++ b/main/http_server/openapi.yaml @@ -164,10 +164,10 @@ components: type: number description: Automatic fan speed control (0=manual, 1=auto) bestDiff: - type: string + type: number description: Best difficulty achieved bestSessionDiff: - type: string + type: number description: Best difficulty achieved in current session boardVersion: type: string