Доработка документации
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
// gpio-monitor-server — HTTP-сервер мониторинга GPIO-шины Raspberry Pi.
|
||||
// Читает поток байт из FIFO pipe, хранит их в кольцевом буфере и бинарных
|
||||
// почасовых логах, отдаёт JSON API и встроенный веб-дашборд на :8080.
|
||||
// Конфигурация — только флагами командной строки (см. main или docs/operations.md).
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -28,6 +32,8 @@ import (
|
||||
//go:embed web/dist web/css web/fonts web/*.html web/*.png
|
||||
var webFiles embed.FS
|
||||
|
||||
// API — состояние HTTP-хендлеров: кольцевой буфер, время старта сервера
|
||||
// и монитор звука. Спецификация ответов — docs/api.md.
|
||||
type API struct {
|
||||
buf *adapter.RingBuffer
|
||||
startTime time.Time
|
||||
@@ -39,7 +45,8 @@ func writeJSON(w http.ResponseWriter, v any) {
|
||||
json.NewEncoder(w).Encode(v)
|
||||
}
|
||||
|
||||
// HandleLogFiles - список доступных лог-файлов
|
||||
// HandleLogFiles отдаёт список бинарных лог-файлов gpio-*.bin,
|
||||
// отсортированный по времени изменения (новые первыми).
|
||||
func (a *API) HandleLogFiles(w http.ResponseWriter, r *http.Request) {
|
||||
dataDir, err := logger.GetDataLogsDir()
|
||||
if err != nil {
|
||||
@@ -105,7 +112,8 @@ func (a *API) HandleLogFiles(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, result)
|
||||
}
|
||||
|
||||
// HandleLogEvents - чтение событий с пагинацией
|
||||
// HandleLogEvents отдаёт события из events_human.log с пагинацией
|
||||
// (page, page_size; страница 1 — самые новые).
|
||||
func (a *API) HandleLogEvents(w http.ResponseWriter, r *http.Request) {
|
||||
// Параметры пагинации
|
||||
page := 1
|
||||
@@ -220,7 +228,9 @@ func (a *API) HandleLogEvents(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
|
||||
// HandleLogData - чтение данных из конкретного bin файла с пагинацией
|
||||
// HandleLogData отдаёт сэмплы одного .bin-файла (параметр file) с пагинацией
|
||||
// (page, page_size; страница 1 — самые новые). Формат записи — 9 байт,
|
||||
// см. docs/data-formats.md. Файл читается в память целиком.
|
||||
func (a *API) HandleLogData(w http.ResponseWriter, r *http.Request) {
|
||||
filename := r.URL.Query().Get("file")
|
||||
if filename == "" {
|
||||
@@ -400,6 +410,8 @@ func (a *API) HandleLogData(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// HandleHealth отдаёт статус сервера: связь с pipe (пороги 15 с и 3 с),
|
||||
// uptime, статистику буфера и уровень звука.
|
||||
func (a *API) HandleHealth(w http.ResponseWriter, r *http.Request) {
|
||||
latest, ok := a.buf.GetLatest()
|
||||
idle := time.Since(a.buf.LastWriteTime())
|
||||
@@ -429,6 +441,7 @@ func (a *API) HandleHealth(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// HandleLatest отдаёт последний байт и до 10 предыдущих (от старых к новым).
|
||||
func (a *API) HandleLatest(w http.ResponseWriter, r *http.Request) {
|
||||
latest, ok := a.buf.GetLatest()
|
||||
if !ok {
|
||||
@@ -442,6 +455,7 @@ func (a *API) HandleLatest(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// HandleHistory отдаёт до 300 последних байт для графика (от старых к новым).
|
||||
func (a *API) HandleHistory(w http.ResponseWriter, r *http.Request) {
|
||||
raw := a.buf.GetLast(300)
|
||||
|
||||
@@ -455,6 +469,9 @@ func (a *API) HandleHistory(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// HandleStream отдаёт статус видеопотока камеры. Внимание: доступность
|
||||
// проверяется по захардкоженному localhost:1984 без учёта флага -camera-url
|
||||
// (известное поведение, docs/tech-debt.md).
|
||||
func (a *API) HandleStream(w http.ResponseWriter, r *http.Request) {
|
||||
// Проверяем доступность MJPEG потока в go2rtc
|
||||
resp, err := http.Get("http://localhost:1984/api/streams?src=cam_mjpeg")
|
||||
@@ -470,7 +487,8 @@ func (a *API) HandleStream(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// Прокси для MJPEG потока — просто ретранслирует готовый поток из go2rtc
|
||||
// handleCamProxy — НЕ ИСПОЛЬЗУЕТСЯ: роутер вызывает handleCamProxyWithURL,
|
||||
// этот вариант с захардкоженным URL остался как мёртвый код (docs/tech-debt.md).
|
||||
func handleCamProxy(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("[cam] запрос от %s", r.RemoteAddr)
|
||||
|
||||
@@ -519,6 +537,8 @@ func handleCamProxy(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// cors разрешает кросс-доменные GET-запросы с любых источников
|
||||
// (рассчитано на доверенную локальную сеть).
|
||||
func cors(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
@@ -703,7 +723,8 @@ func main() {
|
||||
log.Fatal(http.ListenAndServe(*serverPort, nil))
|
||||
}
|
||||
|
||||
// handleCamProxyWithURL проксирует MJPEG поток с указанным URL
|
||||
// handleCamProxyWithURL проксирует MJPEG-поток с cameraURL (флаг -camera-url),
|
||||
// ретранслируя заголовки и сбрасывая буфер после каждого чанка 32 КБ.
|
||||
func handleCamProxyWithURL(w http.ResponseWriter, r *http.Request, cameraURL string) {
|
||||
log.Printf("[cam] запрос от %s к %s", r.RemoteAddr, cameraURL)
|
||||
|
||||
|
||||
@@ -1,37 +1,56 @@
|
||||
# GPIO Monitor Web Interface
|
||||
|
||||
Веб-интерфейс для мониторинга GPIO и видеопотока с камеры.
|
||||
Веб-интерфейс дашборда GPIO Monitor: мониторинг в реальном времени, просмотр исторических логов, видеопоток камеры. Подробная документация фронтенда — [docs/frontend.md](../../../docs/frontend.md).
|
||||
|
||||
## Требования
|
||||
|
||||
- Node.js 20.x или выше
|
||||
- npm 10.x или выше
|
||||
- Go 1.21
|
||||
|
||||
Node.js нужен **только для компиляции TypeScript** — в рантайме фронтенд не имеет зависимостей и раздаётся Go-сервером из встроенных файлов.
|
||||
|
||||
### 1. Установка Node.js и npm на Raspberry Pi
|
||||
|
||||
#### Добавление официального репозитория NodeSource
|
||||
```curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -```
|
||||
|
||||
#### Установка Node.js и npm
|
||||
```sudo apt install -y nodejs```
|
||||
|
||||
#### Проверка установки
|
||||
```node --version # v20.20.2```
|
||||
```npm --version # 10.8.2```
|
||||
|
||||
### 2.Инициализация npm проекта
|
||||
|
||||
#### Переход в директорию с веб-файлами
|
||||
```cd ~/temp/golang/cmd/server/web```
|
||||
|
||||
#### Инициализация package.json
|
||||
```npm init -y```
|
||||
|
||||
#### Установка TypeScript и типов Node.js
|
||||
```npm install -D typescript @types/node```
|
||||
## Установка Node.js на Raspberry Pi
|
||||
|
||||
```bash
|
||||
chmod +x node_modules/.bin/tsc
|
||||
```
|
||||
# Официальный репозиторий NodeSource
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
|
||||
sudo apt install -y nodejs
|
||||
|
||||
# Проверка
|
||||
node --version # v20.x
|
||||
npm --version # 10.x
|
||||
```
|
||||
|
||||
## Сборка
|
||||
|
||||
`package.json` и `tsconfig.json` уже в репозитории — инициализировать проект не нужно, только установить зависимости:
|
||||
|
||||
```bash
|
||||
cd cmd/server/web
|
||||
npm install # однократно
|
||||
npm run build # tsc: js/*.ts → dist/*.js
|
||||
npm run watch # пересборка при изменениях
|
||||
npm run clean # удалить dist/
|
||||
```
|
||||
|
||||
Проще из корня проекта: `make build-frontend` (сам выполнит `npm install` при необходимости).
|
||||
|
||||
> **Важно:** каталог `dist/` не хранится в git, но обязателен для сборки Go-сервера (`go:embed`). Всегда собирайте фронтенд до `go build` — подробности в [docs/development.md](../../../docs/development.md#порядок-сборки).
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
web/
|
||||
├── js/ # TypeScript-исходники (10 модулей, см. docs/frontend.md)
|
||||
├── dist/ # Скомпилированный JS (генерируется tsc)
|
||||
├── css/ # Стили
|
||||
├── fonts/ # Шрифты
|
||||
├── index.html # Редирект на дашборд
|
||||
├── dashboard.html # Мониторинг в реальном времени
|
||||
├── logs.html # Просмотр исторических логов
|
||||
├── favicon.png
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Карта модулей `js/`, взаимодействие с API и цикл разработки — [docs/frontend.md](../../../docs/frontend.md). Спецификация API сервера — [docs/api.md](../../../docs/api.md).
|
||||
|
||||
Reference in New Issue
Block a user