skeleton for testing purposes

This commit is contained in:
lin committed 2026-10-05 14:17:03 +02:00
1 parent 8076b30e3f
commit 71e4f1294e
11 files changed
+273

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
package main
import (
"log"
"rpi5-health/internal/cli"
"rpi5-health/internal/http_internal"
"rpi5-health/internal/system_check"
)
func main() {
srv := http_internal.NewAppServer()
go srv.Start()
memInfo, _ := system_check.GetRamInformation()
const GB = 1024 * 1024 * 1024
log.Printf("Total memory: %dGB\n", memInfo.SystemMemory/GB)
log.Printf("Available memory: %dGB\n", memInfo.AvailableMemory/GB)
log.Printf("Used memory: %dGB\n", memInfo.GetUsedMemory()/GB)
cli.Listen()
}
+5
View File
@@ -0,0 +1,5 @@
module rpi5-health
go 1.26.4
require golang.org/x/sys v0.48.0 // indirect
+2
View File
@@ -0,0 +1,2 @@
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
+36
View File
@@ -0,0 +1,36 @@
package cli
import (
"bufio"
"fmt"
"log"
"os"
"strings"
)
func Listen() {
reader := bufio.NewScanner(os.Stdin)
fmt.Print("> ")
for {
if !reader.Scan() {
log.Println("Program terminated (SIGINT)")
return
}
if err := reader.Err(); err != nil {
log.Printf("Console input error: %v\n", err)
return
}
text := strings.TrimSpace(reader.Text())
switch text {
case "exit":
return
}
}
}
+13
View File
@@ -0,0 +1,13 @@
package errors
func New(text string) error {
return &errorString{text}
}
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
+30
View File
@@ -0,0 +1,30 @@
package http_internal
import "net/http"
type AppServer struct {
srv *http.Server
mux *http.ServeMux
}
func NewAppServer() *AppServer {
mux := http.NewServeMux()
fs := http.FileServer(http.Dir("web/"))
mux.Handle("/", fs)
srv := &http.Server{
Addr: "localhost:1234",
Handler: mux,
}
return &AppServer{
srv: srv,
mux: mux,
}
}
func (srv *AppServer) Start() {
srv.srv.ListenAndServe()
}
+49
View File
@@ -0,0 +1,49 @@
package system_check
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
"strings"
)
var numberRegex *regexp.Regexp = regexp.MustCompile(`\d+`)
func getLinuxRamInfo() (MemoryInformation, error) {
memoryFile, err := os.Open("/proc/meminfo")
if err != nil {
return MemoryInformation{}, fmt.Errorf("Could not find /proc/meminfo. Are you sure you are on linux?")
}
fileReader := bufio.NewScanner(memoryFile)
var TotalMemory uint64
var AvailMemory uint64
for fileReader.Scan() {
if fileReader.Err() != nil {
return MemoryInformation{}, fmt.Errorf("There was an error while reading /proc/meninfo. Error: %v", fileReader.Err())
}
line := fileReader.Text()
if strings.Contains(line, "MemTotal") {
TotalMemory, err = strconv.ParseUint(numberRegex.FindString(line), 10, 64)
if err != nil {
return MemoryInformation{}, fmt.Errorf("Could not parse total memory from /proc/meminfo")
}
} else if strings.Contains(line, "MemAvailable") {
AvailMemory, err = strconv.ParseUint(numberRegex.FindString(line), 10, 64)
if err != nil {
return MemoryInformation{}, fmt.Errorf("Could not parse available memory from /proc/meminfo")
}
}
}
return MemoryInformation{
SystemMemory: TotalMemory,
AvailableMemory: AvailMemory,
}, nil
}
+32
View File
@@ -0,0 +1,32 @@
package system_check
import (
"fmt"
"runtime"
)
type MemoryInformation struct {
/*
* The total amount of memory the system has available
*/
SystemMemory uint64
/*
* How much memory is currently unused
*/
AvailableMemory uint64
}
func (memInfo MemoryInformation) GetUsedMemory() uint64 {
return memInfo.SystemMemory - memInfo.AvailableMemory
}
func GetRamInformation() (MemoryInformation, error) {
switch runtime.GOOS {
case "windows":
return getWinRamInfo(getWindowsTools().ProcGlobalMemoryStatusEx), nil
case "linux":
return getLinuxRamInfo()
default:
return MemoryInformation{}, fmt.Errorf("Unsupported OS: \"%s\"", runtime.GOOS)
}
}
+28
View File
@@ -0,0 +1,28 @@
package system_check
import (
"sync"
"golang.org/x/sys/windows"
)
type WindowsSystemCheckTools struct {
/*
* Win32 API
*/
Kernel32 *windows.LazyDLL
/*
* Windows memory information
*/
ProcGlobalMemoryStatusEx *windows.LazyProc
}
func getWindowsTools() WindowsSystemCheckTools {
kernel32 := sync.OnceValue(func() *windows.LazyDLL { return windows.NewLazySystemDLL("kernel32.dll") })
procGlobalMemoryStatusEx := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GlobalMemoryStatusEx") })
return WindowsSystemCheckTools{
Kernel32: kernel32(),
ProcGlobalMemoryStatusEx: procGlobalMemoryStatusEx(),
}
}
+44
View File
@@ -0,0 +1,44 @@
package system_check
import (
"log"
"unsafe"
"golang.org/x/sys/windows"
)
type memoryStatusEx struct {
/*
* Struct for storing memory status information.
*
* It gets populated via syscall.
*/
dwLength uint32
dwMemoryLoad uint32
ullTotalPhys uint64
ullAvailPhys uint64
ullTotalPageFile uint64
ullAvailPageFile uint64
ullTotalVirtual uint64
ullAvailVirtual uint64
ullAvailExtendedVirtual uint64
}
func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation {
var mem memoryStatusEx
// * Windows requires the dwLength field to be set to the struct's size
// * before execution so it knows which OS struct version is being used.
mem.dwLength = uint32(unsafe.Sizeof(mem))
ret, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mem))) // exec syscall
if ret == 0 { // winapi syscalls return 0 on failure
log.Fatalf("GlobalMemoryStatusEx failed: %v", err)
}
return MemoryInformation{
SystemMemory: mem.ullTotalPhys,
AvailableMemory: mem.ullAvailPhys,
}
}
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>