313 lines
15 KiB
HTML
313 lines
15 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>RSCM-101</title>
|
||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||
<style>
|
||
.tabs-header {
|
||
margin: 0.5em 0;
|
||
background: var(--brand-bg);
|
||
}
|
||
.tabs-header > * {
|
||
display: inline-block;
|
||
}
|
||
.tabs-btn {
|
||
text-decoration: none;
|
||
font-size: 18px;
|
||
border: none;
|
||
padding: 10px 25px;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
margin-bottom: -3px;
|
||
border-bottom: 3px solid #eee;
|
||
}
|
||
.tabs-btn.active {
|
||
color: var(--brand-text);
|
||
border-bottom: 3px solid var(--brand-text);
|
||
}
|
||
.tabs-body-item {
|
||
padding: 20px 0;
|
||
}
|
||
|
||
.indicator_bad {
|
||
background: var(--text-bad);
|
||
}
|
||
.indicator_good {
|
||
background: var(--text-good);
|
||
}
|
||
.indicator {
|
||
display: inline-block;
|
||
width: 1em;
|
||
height: 1em;
|
||
border: solid 1px var(--text-color2);
|
||
border-radius: 0.5em;
|
||
}
|
||
|
||
.state-bar-element {
|
||
margin: 0.5em;
|
||
border-bottom: 2px solid var(--text-color2);
|
||
}
|
||
|
||
.tabs-item-flex-container {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.tabs-item-flex-container > div {
|
||
padding: 1em;
|
||
margin: 1em;
|
||
border: 1px solid var(--text-color2);
|
||
border-radius: 0.2em;
|
||
}
|
||
|
||
.tabs-item-flex-container th {
|
||
text-align: left;
|
||
}
|
||
.tabs-item-flex-container h2 {
|
||
margin-top: 0;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div id="app" hidden>
|
||
<div>
|
||
<span class="state-bar-element">Прием: <span :class="{ indicator_bad: rx.state === true, indicator_good: rx.state === false, indicator: true }"></span></span>
|
||
<span class="state-bar-element">Передача: <span :class="{ indicator_bad: tx.state === true, indicator_good: tx.state === false, indicator: true }"></span></span>
|
||
<span class="state-bar-element">Тест: <span :class="{ indicator_bad: testState === true, indicator_good: testState === false, indicator: true }"></span></span>
|
||
<!-- Последнее обновление: {{ lastUpdateTime }}-->
|
||
</div>
|
||
<div class="tabs">
|
||
<div class="tabs-header">
|
||
<span style="font-weight:bold">RSCM-101</span>
|
||
<a href="#monitoring" class="tabs-btn" @click="activeTab = 'monitoring'" :class="{ active: activeTab === 'monitoring' }">Мониторинг</a>
|
||
<a href="#setup" class="tabs-btn" @click="activeTab = 'setup'" :class="{ active: activeTab === 'setup' }">Настройки</a>
|
||
<a href="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
|
||
</div>
|
||
<div class="tabs-body">
|
||
<div class="tabs-body-item tabs-item-flex-container" v-show="activeTab === 'monitoring'">
|
||
<div>
|
||
<h2>Статистика приема</h2>
|
||
<table>
|
||
<tbody>
|
||
<tr><th>Прием</th><td><span :class="{ indicator_bad: rx.state === true, indicator_good: rx.state === false, indicator: true }"></span></td></tr>
|
||
<tr><th>Захват символьной</th><td><span :class="{ indicator_bad: rx.sym_sync_lock === true, indicator_good: rx.sym_sync_lock === false, indicator: true }"></span></td></tr>
|
||
<tr><th>Захват ФАПЧ</th><td><span :class="{ indicator_bad: rx.freq_search_lock === true, indicator_good: rx.freq_search_lock === false, indicator: true }"></span></td></tr>
|
||
<tr><th>Захват поиска по частоте</th><td><span :class="{ indicator_bad: rx.afc_lock === true, indicator_good: rx.afc_lock === false, indicator: true }"></span></td></tr>
|
||
<tr><th>Захват пакетной синхр.</th><td><span :class="{ indicator_bad: rx.pkt_sync === true, indicator_good: rx.pkt_sync === false, indicator: true }"></span></td></tr>
|
||
<tr><th>ОСШ/RSSI</th><td>{{ rx.snr }} / {{ rx.rssi }}</td></tr>
|
||
<tr><th>Modcod/размер кадра</th><td>{{ rx.modcod }} / {{ rx.frameSize }}</td></tr>
|
||
<tr><th>Пилот-символы</th><td>{{ rx.pilots }}</td></tr>
|
||
<tr><th>Символьная ошибка</th><td>{{ rx.symError }}</td></tr>
|
||
<tr><th>Грубая/точная част. ошибка, Гц</th><td>{{ rx.freqErr }} / {{ rx.freqErrAcc }}</td></tr>
|
||
<tr><th>Ур. входного сигнала</th><td>{{ rx.inputSignalLevel }}</td></tr>
|
||
<tr><th>Ошибка ФАПЧ</th><td>{{ rx.pllError }}</td></tr>
|
||
<tr><th>Инф. скорость на приеме</th><td>{{ rx.speedOnRx }} kbit/s</td></tr>
|
||
<tr><th>Инф. скорость на интерфейсе</th><td>{{ rx.speedOnIif }} kbit/s</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p> Статистика пакетов </p>
|
||
<table>
|
||
<tbody>
|
||
<tr><th>Качественных пакетов</th><td>{{ rx.packetsOk }}</td></tr>
|
||
<tr><th>Поврежденных пакетов</th><td>{{ rx.packetsBad }}</td></tr>
|
||
<tr><th>DUMMY</th><td>{{ rx.packetsDummy }}</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<button> Сброс статистики </button>
|
||
</div>
|
||
<div>
|
||
<h2>Статистика передачи</h2>
|
||
<table>
|
||
<tbody>
|
||
<tr><th>Передача</th><td><span :class="{ indicator_bad: tx.state === true, indicator_good: tx.state === false, indicator: true }"></span></td></tr>
|
||
<tr><th>ОСШ дальнего приема</th><td>{{ tx.snr }}</td></tr>
|
||
<tr><th>Modcod</th><td>{{ tx.modcod }}</td></tr>
|
||
<tr><th>Размер кадра</th><td>{{ tx.frameSize }}</td></tr>
|
||
<tr><th>Пилот-символы</th><td>{{ tx.pilots }}</td></tr>
|
||
<tr><th>Инф. скорость на передаче</th><td>{{ tx.speedOnTx }} kbit/s</td></tr>
|
||
<tr><th>Инф. скорость на интерфейсе</th><td>{{ tx.speedOnIif }} kbit/s</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div>
|
||
<h2>Статистика режима CinC</h2>
|
||
<table>
|
||
<tbody>
|
||
<tr><th>ОСС</th><td class="value-bad">indcator</td></tr>
|
||
<tr><th>Захват коррелятора</th><td class="value-bad"><span :class="{ indicator: true }"></span> bool</td></tr>
|
||
<tr><th>Кол-во срывов коррелятора</th><td class="value-bad">indcator</td></tr>
|
||
<tr><th>Грубая/точная част. ошибка, Гц</th><td class="value-bad">indcator/indicator</td></tr>
|
||
<tr><th>Задержка в канале, мс</th><td class="value-bad">indcator</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div>
|
||
<h2>Состояние устройства</h2>
|
||
<table>
|
||
<tbody>
|
||
<tr><th>Температура ADRV</th><td class="value-bad">indcator °C</td></tr>
|
||
<tr><th>Температура ZYNC</th><td class="value-bad">indcator °C</td></tr>
|
||
<tr><th>Температура FPGA</th><td class="value-bad">indcator °C</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="tabs-body-item tabs-item-flex-container" v-show="activeTab === 'setup'">
|
||
<div>
|
||
<h2>Настройка передатчика</h2>
|
||
<div>
|
||
<div>
|
||
...
|
||
</div>
|
||
<h3>Параметры передачи</h3>
|
||
<div>
|
||
...
|
||
</div>
|
||
<h3>Режим работы DVB-S2</h3>
|
||
<div>
|
||
...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h2>Настройка приемника</h2>
|
||
</div>
|
||
<div>
|
||
<h2>Настройки режима CinC</h2>
|
||
<p>CinC пока нельзя настроить, но скоро разработчик это поправит)</p>
|
||
</div>
|
||
<div>
|
||
<h2>Настройки питания и опорного генератора</h2>
|
||
<p>Эти настройки пока недоступны, но скоро разработчик это поправит)</p>
|
||
</div>
|
||
</div>
|
||
<div class="tabs-body-item" v-show="activeTab === 'admin'">
|
||
<p>
|
||
Эти настройки пока недоступны, но скоро разработчик это поправит. А пока смотри на крокодила
|
||
</p>
|
||
<img src="/images/krokodil_vzryvaetsya_hd.gif" alt="krokodil">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Версия для разработки включает в себя возможность вывода в консоль полезных уведомлений -->
|
||
<script src="/js/vue.js"></script>
|
||
<script>
|
||
// const router = useRouter();
|
||
const availableTabs = ['monitoring', 'setup', 'admin']
|
||
const defaultTab = availableTabs[0]
|
||
|
||
function getCurrentTab() {
|
||
const sl = window.location.hash.slice(1)
|
||
if (availableTabs.indexOf(sl) >= 0) {
|
||
return sl
|
||
}
|
||
return defaultTab
|
||
}
|
||
|
||
const app = new Vue({
|
||
el: '#app',
|
||
data: {
|
||
rx: {
|
||
// индикаторы
|
||
state: '?', // общее состояние
|
||
sym_sync_lock: '?', // захват символьной
|
||
freq_search_lock: '?', // Захват поиска по частоте
|
||
afc_lock: '?', // захват ФАПЧ
|
||
pkt_sync: '?', // захват пакетной синхронизации
|
||
|
||
// куча других параметров, идет в том же порядке, что и в таблице
|
||
snr: 0, rssi: -105,
|
||
modcod: 0, frameSize: 0,
|
||
pilots: '?',
|
||
symError: 0.0,
|
||
freqErr: 0, freqErrAcc: 0,
|
||
inputSignalLevel: 0,
|
||
pllError: 0,
|
||
speedOnRx: 0,
|
||
speedOnIif: 0,
|
||
|
||
// статистика пакетов
|
||
packetsOk: 0,
|
||
packetsBad: 0,
|
||
packetsDummy: 0,
|
||
},
|
||
|
||
tx: {
|
||
// состояние
|
||
state: '?',
|
||
|
||
// прочие поля
|
||
snr: -90,
|
||
modcod: -90,
|
||
frameSize: 'normal',
|
||
pilots: 'no pilots',
|
||
speedOnTx: 0,
|
||
speedOnIif: 0,
|
||
},
|
||
|
||
testState: '?',
|
||
lastUpdateTime: new Date(),
|
||
|
||
activeTab: getCurrentTab()
|
||
},
|
||
methods: {
|
||
updateMainState(vals) {
|
||
this.lastUpdateTime = new Date();
|
||
|
||
this.rx.state = vals["mainState"]["rx.state"]
|
||
this.rx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"]
|
||
this.rx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"]
|
||
this.rx.afc_lock = vals["mainState"]["rx.afc_lock"]
|
||
this.rx.pkt_sync = vals["mainState"]["rx.pkt_sync"]
|
||
this.rx.snr = vals["mainState"]["rx.snr"]
|
||
this.rx.rssi = vals["mainState"]["rx.rssi"]
|
||
this.rx.modcod = vals["mainState"]["rx.modcod"]
|
||
this.rx.frameSize = vals["mainState"]["rx.frameSize"]
|
||
this.rx.pilots = vals["mainState"]["rx.pilots"]
|
||
this.rx.symError = vals["mainState"]["rx.symError"]
|
||
this.rx.freqErr = vals["mainState"]["rx.freqErr"]
|
||
this.rx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"]
|
||
this.rx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"]
|
||
this.rx.pllError = vals["mainState"]["rx.pllError"]
|
||
this.rx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"]
|
||
this.rx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"]
|
||
this.rx.packetsOk = vals["mainState"]["rx.packetsOk"]
|
||
this.rx.packetsBad = vals["mainState"]["rx.packetsBad"]
|
||
this.rx.packetsDummy = vals["mainState"]["rx.packetsDummy"]
|
||
|
||
this.tx.state = vals["mainState"]["tx.state"]
|
||
this.tx.snr = vals["mainState"]["rx.snr"]
|
||
this.tx.modcod = vals["mainState"]["rx.modcod"]
|
||
this.tx.frameSize = vals["mainState"]["rx.frameSize"]
|
||
this.tx.pilots = vals["mainState"]["rx.pilots"]
|
||
this.tx.speedOnTxKbit = vals["mainState"]["rx.speedOnTxKbit"]
|
||
this.tx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"]
|
||
|
||
this.testState = vals["mainState"]["testState"]
|
||
}
|
||
},
|
||
mounted() {
|
||
const doFetch = async () => {
|
||
let d = await fetch("/api/mainStatistics")
|
||
this.updateMainState(await d.json())
|
||
}
|
||
|
||
doFetch().then(() => {
|
||
setInterval(() => { doFetch().then(() => {}) }, 1000);
|
||
});
|
||
}
|
||
})
|
||
|
||
document.getElementById("app").removeAttribute("hidden")
|
||
|
||
// import MyComponent from './modules/header'
|
||
// const sh = new Vue(MyComponent)
|
||
</script>
|
||
</body>
|
||
</html> |