Connector Open-Source Code
Browse connector files locally. Exchange API keys stay on your device.
ui/diagnostics.php
<?php
// /opt/nuxvision_connector/ui/diagnostics.php
declare(strict_types=1);
require_once __DIR__ . '/common.php';
function diag_bool_icon(bool $ok): string {
return $ok
? '<span class="text-success"><i class="bi bi-check-circle-fill me-1"></i>OK</span>'
: '<span class="text-danger"><i class="bi bi-x-circle-fill me-1"></i>FAIL</span>';
}
function diag_card(string $title, bool $ok, string $bodyHtml): void {
?>
<div class="nv-card p-4 mb-3">
<div class="d-flex align-items-center justify-content-between mb-2">
<div class="h5 fw-bold m-0"><?=h($title)?></div>
<div><?=diag_bool_icon($ok)?></div>
</div>
<div class="nv-muted2 small"><?= $bodyHtml ?></div>
</div>
<?php
}
function http_probe(string $url, int $timeout = 6): array {
[$code, $err, $body, $json] = curl_json($url, [], $timeout);
$ok = ($err === '' && $code >= 200 && $code < 400);
return [
'ok'=>$ok,
'http'=>$code,
'err'=>$err,
'raw'=>is_string($body)?substr($body,0,200):null,
'json'=>$json
];
}
/**
* Normalize a base url:
* - if already ends with /api/v<number>, keep it
* - otherwise append /api/v1
*/
function nv_normalize_base(string $base): string {
$base = rtrim(trim($base), '/');
if ($base === '') return '';
if (preg_match('~/api/v\d+$~', $base)) return $base;
return $base . '/api/v1';
}
function nv_call_get(string $nvBase, string $nvKey, string $path, array $query, int $timeout): array {
$nvBase = nv_normalize_base($nvBase);
$url = $nvBase . '/' . ltrim($path, '/');
if ($query) $url .= '?' . http_build_query($query);
[$code, $err, $body, $json] = curl_json($url, nv_auth_headers($nvKey), $timeout);
$ok = ($err === '' && $code >= 200 && $code < 400 && is_array($json));
return [
'ok' => $ok,
'http' => $code,
'err' => $err,
'raw' => is_string($body) ? substr($body, 0, 200) : null,
'json' => $json,
'url' => $url,
];
}
/* -------------------- Choose instance_id -------------------- */
$instanceId = to_int($_GET['instance_id'] ?? 0, 0);
if ($instanceId <= 0) {
$sid = nv_instance_id_from_session();
if ($sid > 0) $instanceId = $sid;
}
/* -------------------- Load config (prefer local instance config) -------------------- */
$wiz = wiz_get();
$nv_base = '';
$nv_key = '';
$nv_to = 6;
$ex_name = 'bitkub';
$ex_key = '';
$ex_sec = '';
$cfgPath = '';
if ($instanceId > 0) {
$cfgPath = nv_instance_config_path($instanceId);
if (is_file($cfgPath)) {
$cfg = @require $cfgPath;
if (is_array($cfg)) {
$nv_base = trim((string)($cfg['nuxvision']['base_url'] ?? ''));
$nv_key = trim((string)($cfg['nuxvision']['api_key'] ?? ''));
$nv_to = to_int($cfg['nuxvision']['timeout'] ?? 6, 6);
$ex_name = (string)($cfg['exchange']['name'] ?? $ex_name);
$ex_key = trim((string)($cfg['exchange']['api_key'] ?? ''));
$ex_sec = trim((string)($cfg['exchange']['api_secret'] ?? ''));
}
}
}
/* fallback to wizard session if missing */
if ($nv_base === '') $nv_base = trim((string)v($wiz, 'nuxvision.base_url', ''));
if ($nv_key === '') $nv_key = trim((string)v($wiz, 'nuxvision.api_key', ''));
$tmpInst = to_int(v($wiz, 'nuxvision.instance_id', 0), 0);
if ($instanceId <= 0 && $tmpInst > 0) $instanceId = $tmpInst;
$nv_to = to_int($nv_to, 6);
if ($nv_to < 2 || $nv_to > 30) $nv_to = 6;
if ($ex_name === '' || $ex_name === '0') $ex_name = (string)v($wiz, 'exchange.name', $ex_name);
if ($ex_key === '') $ex_key = trim((string)v($wiz, 'exchange.api_key', ''));
if ($ex_sec === '') $ex_sec = trim((string)v($wiz, 'exchange.api_secret', ''));
render_header('NuxVision Connector', 'Diagnostics', false);
render_flash();
?>
<div class="row g-3">
<div class="col-lg-8">
<div class="nv-card p-4 mb-3">
<div class="h4 fw-bold mb-1">Diagnostics</div>
<div class="nv-muted mb-2">Quick checks for connectivity and runtime configuration.</div>
<div class="smallhint">
Tip: if something fails, check DNS, firewall, or server time (TLS can fail when clock is wrong).
</div>
</div>
<?php
// 1) Internet probe
$internet = http_probe('https://www.google.com/generate_204', 6);
$internetOk = !empty($internet['ok']);
diag_card(
'Internet connectivity',
$internetOk,
'HTTP: <span class="mono">'.h((string)$internet['http']).'</span>'
.($internet['err'] ? ' • Error: <span class="mono">'.h((string)$internet['err']).'</span>' : '')
);
// 2) NuxVision probe (heartbeat + instance_settings)
$nvOk = false;
$nvBody = '';
if ($nv_base === '' || !is_valid_url($nv_base)) {
$nvBody = 'Invalid base URL: <span class="mono">'.h($nv_base ?: '—').'</span>';
} elseif ($nv_key === '') {
$nvBody = 'Missing API key (from local instance config or wizard session).';
} elseif ($instanceId <= 0) {
$nvBody = 'Missing instance_id (add <span class="mono">?instance_id=1</span> or select an instance in UI).';
} else {
$hb = nv_call_get($nv_base, $nv_key, 'heartbeat.php', ['instance_id' => $instanceId], $nv_to);
$hbOk = !empty($hb['ok']) && !empty($hb['json']) && (!empty($hb['json']['ok']) || (($hb['json']['status'] ?? '') === 'ok'));
$nvBody .= 'Base: <span class="mono">'.h(nv_normalize_base($nv_base)).'</span>';
$nvBody .= '<br>Heartbeat URL: <span class="mono">'.h((string)$hb['url']).'</span>';
$nvBody .= '<br>Heartbeat: '.($hbOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
.' • HTTP <span class="mono">'.h((string)($hb['http'] ?? 0)).'</span>';
if (!$hbOk) {
if (!empty($hb['err'])) $nvBody .= '<br>Error: <span class="mono">'.h((string)$hb['err']).'</span>';
if (!empty($hb['raw'])) $nvBody .= '<br>Raw: <span class="mono">'.h((string)$hb['raw']).'</span>';
}
// settings endpoint = validates “config fetched from NuxVision”
$st = nv_call_get($nv_base, $nv_key, 'instance_settings.php', ['instance_id' => $instanceId], $nv_to);
$stOk = !empty($st['ok']) && !empty($st['json']) && !empty($st['json']['ok']) && is_array($st['json']['settings'] ?? null);
$nvBody .= '<br><br>Settings URL: <span class="mono">'.h((string)$st['url']).'</span>';
$nvBody .= '<br>Instance settings: '.($stOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
.' • HTTP <span class="mono">'.h((string)($st['http'] ?? 0)).'</span>';
if ($stOk) {
$count = count((array)($st['json']['settings'] ?? []));
$nvBody .= ' • keys=<span class="mono">'.h((string)$count).'</span>';
$nvOk = true; // we consider NV OK when settings works
} else {
if (!empty($st['err'])) $nvBody .= '<br>Error: <span class="mono">'.h((string)$st['err']).'</span>';
if (!empty($st['raw'])) $nvBody .= '<br>Raw: <span class="mono">'.h((string)$st['raw']).'</span>';
$nvOk = false;
}
}
diag_card('NuxVision API', $nvOk, $nvBody);
// 3) Exchange probe (public only)
$exOk = false;
$exBody = 'Exchange: <span class="mono">'.h($ex_name ?: '—').'</span>';
if (strtolower($ex_name) !== 'bitkub') {
$exBody .= '<br>Public probe not implemented for this exchange.';
} else {
$pub = http_probe('https://api.bitkub.com/api/v3/servertime', 6);
$pubOk = !empty($pub['ok']);
$exBody .= '<br>Public servertime: '.($pubOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
.' • HTTP <span class="mono">'.h((string)$pub['http']).'</span>';
if ($ex_key === '' || $ex_sec === '') {
$exBody .= '<br>Private test skipped: missing API key/secret (local config or wizard session).';
} else {
$exBody .= '<br>Private test: skipped in UI (runner validates during runtime).';
}
$exOk = $pubOk;
}
diag_card('Exchange API', $exOk, $exBody);
?>
<div class="d-flex gap-2 mt-2">
<a class="btn btn-soft" href="./index.php"><i class="bi bi-house me-1"></i>Home</a>
<?php if ($instanceId > 0): ?>
<a class="btn btn-soft" href="./diagnostics.php?instance_id=<?=h((string)$instanceId)?>">
<i class="bi bi-arrow-clockwise me-1"></i>Refresh
</a>
<?php endif; ?>
</div>
</div>
<div class="col-lg-4">
<div class="nv-card p-4">
<div class="h5 fw-bold mb-2">Current config</div>
<div class="smallhint mb-2">Prefer local instance config; fallback to wizard session.</div>
<div class="smallhint mb-2">
Instance ID<br>
<span class="mono"><?=h((string)$instanceId ?: '—')?></span>
</div>
<div class="smallhint mb-2">
Config file<br>
<span class="mono"><?=h($cfgPath ?: '—')?></span>
</div>
<div class="smallhint mb-2">
NuxVision base URL<br>
<span class="mono"><?=h($nv_base ?: '—')?></span>
</div>
<div class="smallhint mb-2">
Normalized base<br>
<span class="mono"><?=h($nv_base ? nv_normalize_base($nv_base) : '—')?></span>
</div>
<div class="smallhint mb-2">
Exchange<br>
<span class="mono"><?=h($ex_name ?: '—')?></span>
</div>
</div>
</div>
</div>
<?php
render_footer();