first ui working

This commit is contained in:
Andres Bott
2025-08-16 15:45:30 +02:00
parent faebae2dd3
commit 8ab494beac
24 changed files with 1393 additions and 9 deletions

View File

@@ -1,4 +1,6 @@
SHELL := /bin/bash
COMMIT_SHA_SHORT ?= $(shell git rev-parse --short=12 HEAD)
PWD_DIR := ${CURDIR}
default: help;
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
@@ -7,6 +9,82 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
# ======================================================================================
##@ Build
build: ## builds the web UI and packages it (use VERSION=v1.2.3 or defaults to commit-SNAPSHOT)
@echo "Building web UI..."
@cd webui && make build
@echo "Creating package..."
@mkdir -p dist
@VERSION=$${VERSION:-$(COMMIT_SHA_SHORT)-SNAPSHOT} && \
PACKAGE_NAME="nanoSmart-$$VERSION" && \
mkdir -p "dist/$$PACKAGE_NAME/cron" && \
mkdir -p "dist/$$PACKAGE_NAME/webui" && \
cp -r webui/dist/assets "dist/$$PACKAGE_NAME/webui/" && \
cp -r webui/dist/icons "dist/$$PACKAGE_NAME/webui/" && \
cp webui/dist/index.html "dist/$$PACKAGE_NAME/webui/" && \
cp -r cron/smart_monitor.conf "dist/$$PACKAGE_NAME/cron/smart_monitor.conf" && \
cp -r cron/smart_monitor.sh "dist/$$PACKAGE_NAME/cron/smart_monitor.sh" && \
cp LICENSE "dist/$$PACKAGE_NAME/" && \
cp README.md "dist/$$PACKAGE_NAME/" && \
cd dist && zip -r "$$PACKAGE_NAME.zip" "$$PACKAGE_NAME/" && \
rm -rf "$$PACKAGE_NAME" && \
echo "Package created: dist/$$PACKAGE_NAME.zip" && \
echo "Package size: $$(du -h "$$PACKAGE_NAME.zip" | cut -f1)"
clean: ## clean the build environment
@rm -rf ./dist
##@ Release
check_env: # check for needed envs
ifndef GITHUB_TOKEN
$(error GITHUB_TOKEN is undefined, create one with repo permissions here: https://github.com/settings/tokens/new?scopes=repo,write%3Apackages )
endif
@[ "${version}" ] || ( echo ">> version is not set, usage: make release version=\"v1.2.3\" "; exit 1 )
@which jq > /dev/null || ( echo ">> jq is not installed. Please install jq for JSON parsing."; exit 1 )
.PHONY: check-git-clean
check-git-clean: # check if git repo is clen
@git diff --quiet
.PHONY: check-branch
check-branch:
@current_branch=$$(git symbolic-ref --short HEAD) && \
if [ "$$current_branch" != "main" ]; then \
echo "Error: You are on branch '$$current_branch'. Please switch to 'main'."; \
exit 1; \
fi
#release: check_env check-branch check-git-clean ## release a new version, call with version="v1.2.3", make sure to have valid GH token
release: check_env check-branch check-git-clean ## release a new version, call with version="v1.2.3", make sure to have valid GH token
@[ "${version}" ] || ( echo ">> version is not set, usage: make release version=\"v1.2.3\" "; exit 1 )
@echo "Building release package for version $(version)..."
@VERSION=$(version) make build
@echo "Creating GitHub release..."
@git tag -d $(version) || true
@git tag -a $(version) -m "Release version: $(version)"
@git push --delete origin $(version) || true
@git push origin $(version) || true
@echo "Creating GitHub release..."
@RELEASE_ID=$$(curl -s -H "Authorization: token $(GITHUB_TOKEN)" \
-H "Accept: application/vnd.github.v3+json" \
-X POST \
-d '{"tag_name":"$(version)","name":"Release $(version)","body":"Release version $(version)","draft":false,"prerelease":false}' \
"https://api.github.com/repos/ansible-autobott/nanoSmart/releases" | \
jq -r '.id') && \
if [ "$$RELEASE_ID" = "null" ] || [ -z "$$RELEASE_ID" ]; then \
echo "Error: Could not create release for tag $(version)"; \
exit 1; \
fi && \
echo "Release created with ID: $$RELEASE_ID" && \
echo "Uploading release assets..." && \
curl -s -H "Authorization: token $(GITHUB_TOKEN)" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/zip" \
--data-binary @dist/nanoSmart-$(version).zip \
"https://uploads.github.com/repos/ansible-autobott/nanoSmart/releases/$$RELEASE_ID/assets?name=nanoSmart-$(version).zip" && \
echo "Release $(version) created and asset uploaded successfully!"
##@ Help

View File

@@ -1,2 +1,13 @@
# nanoSmart
micro UI for displaying SMART data
![Overview](zarf/screenshots/overview.jpg)
![Detail](zarf/screenshots/detail.jpg)
## How it works
nanoSmart is composed of 2 components:
a) a cron script that generates static json files to a specific location
b) an SPA that can consume the static json and represent relevant information

View File

@@ -5,21 +5,21 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="48x48" href="/favicon-48x48.png">
<link rel="icon" type="image/x-icon" href="/icons/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48x48.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="144x144" href="/icons/apple-touch-icon-144x144.png">
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest">
<link rel="manifest" href="/icons/site.webmanifest">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#3b82f6">
<meta name="msapplication-TileImage" content="/android-chrome-144x144.png">
<meta name="msapplication-TileImage" content="/icons/android-chrome-144x144.png">
<meta name="theme-color" content="#3b82f6">
<title>nano Smart</title>

View File

@@ -0,0 +1,87 @@
{
"device": "/dev/nvme1n1",
"timestamp": 1755340242,
"smart_data": {
"device_info": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-i", "-j", "/dev/nvme1n1"],
"exit_status": 0
},
"local_time": {
"time_t": 1755340242,
"asctime": "Sat Aug 16 12:30:42 2025 CEST"
},
"device": {
"name": "/dev/nvme1n1",
"info_name": "/dev/nvme1n1",
"type": "nvme",
"protocol": "NVMe"
},
"model_name": "INTEL SSDPE2KX080T8",
"serial_number": "INTEL987654321",
"firmware_version": "REDACTED",
"nvme_total_capacity": 8001563222016,
"nvme_unallocated_capacity": 0,
"nvme_controller_id": 1,
"nvme_ieee_oui_identifier": 6083300,
"nvme_number_of_namespaces": 128,
"nvme_pci_vendor": {
"id": 32902,
"subsystem_id": 32902
},
"nvme_version": {
"string": "1.2",
"value": 66048
},
"smart_support": {
"available": true,
"enabled": true
}
},
"smart_attributes": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-A", "-j", "/dev/nvme1n1"],
"exit_status": 0
},
"nvme_smart_health_information_log": {
"critical_warning": 1,
"temperature": 75,
"available_spare": 85,
"available_spare_threshold": 10,
"percentage_used": 85,
"data_units_read": 20126802,
"data_units_written": 184919244,
"host_reads": 134106494,
"host_writes": 4922206599,
"controller_busy_time": 165,
"power_cycles": 22,
"power_on_hours": 45678,
"unsafe_shutdowns": 8,
"media_errors": 2,
"num_err_log_entries": 5,
"warning_temp_time": 120,
"critical_comp_time": 0
}
},
"smart_health": {
"smart_status": {
"nvme": {
"value": 1
},
"passed": false
}
},
"smart_errors": {},
"smart_selftest": {}
}
}

View File

@@ -0,0 +1,467 @@
{
"device": "/dev/sda",
"timestamp": 1755340242,
"smart_data": {
"device_info": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-i", "-j", "/dev/sda"],
"exit_status": 0
},
"local_time": {
"time_t": 1755340242,
"asctime": "Sat Aug 16 12:30:42 2025 CEST"
},
"device": {
"name": "/dev/sda",
"info_name": "/dev/sda",
"type": "sat",
"protocol": "SATA"
},
"model_name": "INTEL SSDSC2BB240G4",
"serial_number": "INTEL123456789",
"firmware_version": "XCV10132",
"user_capacity": {
"blocks": 468862128,
"bytes": 240057809920
},
"logical_block_size": 512,
"smart_support": {
"available": true,
"enabled": true
}
},
"smart_attributes": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-A", "-j", "/dev/sda"],
"exit_status": 0
},
"table": [
{
"id": 5,
"name": "Reallocated_Sector_Ct",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 9,
"name": "Power_On_Hours",
"value": 85,
"worst": 85,
"thresh": 0,
"raw": {"value": 69412, "string": "69412"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 12,
"name": "Power_Cycle_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 55, "string": "55"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 170,
"name": "Available_Reservd_Space",
"value": 100,
"worst": 100,
"thresh": 10,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 171,
"name": "Program_Fail_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 172,
"name": "Erase_Fail_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 173,
"name": "Wear_Leveling_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 174,
"name": "Unexpected_Power_Loss_Ct",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 3, "string": "3"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 184,
"name": "End-to-End_Error",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 187,
"name": "Reported_Uncorrect",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 194,
"name": "Temperature_Celsius",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 35, "string": "35"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "-O---- "
}
},
{
"id": 195,
"name": "Hardware_ECC_Recovered",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 199,
"name": "UDMA_CRC_Error_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 202,
"name": "Data_Address_Mark_Errs",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 225,
"name": "Load_Cycle_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 226,
"name": "Load_In_Time",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 227,
"name": "Torque_Amplification_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 228,
"name": "Power-Off_Retract_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 232,
"name": "Available_Reservd_Space",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 233,
"name": "Media_Wearout_Indicator",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 234,
"name": "Average_Erase_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 235,
"name": "Max_Erase_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 241,
"name": "Total_LBAs_Written",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 242,
"name": "Total_LBAs_Read",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
}
]
},
"smart_health": {
"smart_status": {
"passed": true
}
},
"smart_errors": {},
"smart_selftest": {}
}
}

View File

@@ -0,0 +1,315 @@
{
"device": "/dev/sdb",
"timestamp": 1755340242,
"smart_data": {
"device_info": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-i", "-j", "/dev/sdb"],
"exit_status": 0
},
"local_time": {
"time_t": 1755340242,
"asctime": "Sat Aug 16 12:30:42 2025 CEST"
},
"device": {
"name": "/dev/sdb",
"info_name": "/dev/sdb",
"type": "sat",
"protocol": "SATA"
},
"model_name": "SEAGATE ST373453LC",
"serial_number": "SEAGATE123456",
"firmware_version": "DX10",
"user_capacity": {
"blocks": 143374650,
"bytes": 73407820800
},
"logical_block_size": 512,
"rotation_rate": 15015,
"smart_support": {
"available": true,
"enabled": true
}
},
"smart_attributes": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-A", "-j", "/dev/sdb"],
"exit_status": 0
},
"table": [
{
"id": 1,
"name": "Raw_Read_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 16,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
},
{
"id": 2,
"name": "Throughput_Performance",
"value": 136,
"worst": 136,
"thresh": 54,
"raw": {"value": 108, "string": "108"},
"flags": {
"prefailure": true,
"updated_online": false,
"performance": true,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "POS--- "
}
},
{
"id": 3,
"name": "Spin_Up_Time",
"value": 134,
"worst": 134,
"thresh": 24,
"raw": {"value": 222, "string": "222 (Average 222)"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": true,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "POS--- "
}
},
{
"id": 4,
"name": "Start_Stop_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 12, "string": "12"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 5,
"name": "Reallocated_Sector_Ct",
"value": 100,
"worst": 100,
"thresh": 36,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 7,
"name": "Seek_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 30,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
},
{
"id": 9,
"name": "Power_On_Hours",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 102880, "string": "102880"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 10,
"name": "Spin_Retry_Count",
"value": 100,
"worst": 100,
"thresh": 97,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 12,
"name": "Power_Cycle_Count",
"value": 100,
"worst": 100,
"thresh": 20,
"raw": {"value": 12, "string": "12"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 194,
"name": "Temperature_Celsius",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 33, "string": "33"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "-O---- "
}
},
{
"id": 195,
"name": "Hardware_ECC_Recovered",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 197,
"name": "Current_Pending_Sector",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 198,
"name": "Offline_Uncorrectable",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 199,
"name": "UDMA_CRC_Error_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 200,
"name": "Multi_Zone_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
}
]
},
"smart_health": {
"smart_status": {
"passed": true
}
},
"smart_errors": {},
"smart_selftest": {}
}
}

View File

@@ -0,0 +1,315 @@
{
"device": "/dev/sdc",
"timestamp": 1755340242,
"smart_data": {
"device_info": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-i", "-j", "/dev/sdc"],
"exit_status": 0
},
"local_time": {
"time_t": 1755340242,
"asctime": "Sat Aug 16 12:30:42 2025 CEST"
},
"device": {
"name": "/dev/sdc",
"info_name": "/dev/sdc",
"type": "scsi",
"protocol": "SCSI"
},
"model_name": "HGST HUS724020ALA640",
"serial_number": "HGST123456789",
"firmware_version": "A21D",
"user_capacity": {
"blocks": 3907029168,
"bytes": 2000398934016
},
"logical_block_size": 512,
"rotation_rate": 7200,
"smart_support": {
"available": true,
"enabled": true
}
},
"smart_attributes": {
"json_format_version": [1, 0],
"smartctl": {
"version": [7, 3],
"svn_revision": "5338",
"platform_info": "x86_64-linux-6.1.0-37-amd64",
"build_info": "(local build)",
"argv": ["smartctl", "-A", "-j", "/dev/sdc"],
"exit_status": 0
},
"table": [
{
"id": 1,
"name": "Raw_Read_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 16,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
},
{
"id": 2,
"name": "Throughput_Performance",
"value": 136,
"worst": 136,
"thresh": 54,
"raw": {"value": 108, "string": "108"},
"flags": {
"prefailure": true,
"updated_online": false,
"performance": true,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "POS--- "
}
},
{
"id": 3,
"name": "Spin_Up_Time",
"value": 134,
"worst": 134,
"thresh": 24,
"raw": {"value": 222, "string": "222 (Average 222)"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": true,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "POS--- "
}
},
{
"id": 4,
"name": "Start_Stop_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 8, "string": "8"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 5,
"name": "Reallocated_Sector_Ct",
"value": 100,
"worst": 100,
"thresh": 36,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 7,
"name": "Seek_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 30,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
},
{
"id": 9,
"name": "Power_On_Hours",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 8760, "string": "8760"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 10,
"name": "Spin_Retry_Count",
"value": 100,
"worst": 100,
"thresh": 97,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 12,
"name": "Power_Cycle_Count",
"value": 100,
"worst": 100,
"thresh": 20,
"raw": {"value": 8, "string": "8"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 194,
"name": "Temperature_Celsius",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 28, "string": "28"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": false,
"auto_keep": false,
"string": "-O---- "
}
},
{
"id": 195,
"name": "Hardware_ECC_Recovered",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 197,
"name": "Current_Pending_Sector",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 198,
"name": "Offline_Uncorrectable",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "PO--CK "
}
},
{
"id": 199,
"name": "UDMA_CRC_Error_Count",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": false,
"updated_online": true,
"performance": false,
"error_rate": false,
"event_count": true,
"auto_keep": true,
"string": "-O--CK "
}
},
{
"id": 200,
"name": "Multi_Zone_Error_Rate",
"value": 100,
"worst": 100,
"thresh": 0,
"raw": {"value": 0, "string": "0"},
"flags": {
"prefailure": true,
"updated_online": true,
"performance": false,
"error_rate": true,
"event_count": false,
"auto_keep": false,
"string": "PO-R-- "
}
}
]
},
"smart_health": {
"smart_status": {
"passed": true
}
},
"smart_errors": {},
"smart_selftest": {}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,46 @@
{
"name": "nano Smart",
"short_name": "nanoSmart",
"description": "SMART Monitoring Tool for Storage Devices",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3b82f6",
"icons": [
{
"src": "/favicon-16x16.png",
"sizes": "16x16",
"type": "image/png"
},
{
"src": "/favicon-32x32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "/favicon-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/apple-touch-icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
},
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

View File

@@ -58,7 +58,7 @@ const viewDetails = (device) => {
<template>
<div class="overview-container">
<div class="page-header">
<h1>SMART Monitor</h1>
<h1 class="font-semibold" style="font-size: 2rem">nano SMART</h1>
</div>
<Card class="devices-table-card">

View File

@@ -15,6 +15,15 @@ export default defineConfig({
}
},
base: "/",
build: {
assetsDir: 'assets',
rollupOptions: {
input: {
main: fileURLToPath(new URL('./index.html', import.meta.url))
}
}
},
publicDir: 'public',
server: {
proxy: {
'/auth': { // This is the path you want to proxy

BIN
zarf/icon/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

56
zarf/icon/icon.svg Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg5"
xml:space="preserve"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="icon.svg"
inkscape:export-filename="icon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.67741382"
inkscape:cx="804.53038"
inkscape:cy="541.02823"
inkscape:window-width="2560"
inkscape:window-height="1367"
inkscape:window-x="2560"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs2" /><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><g
id="g2379"
transform="matrix(1.2254002,0,0,1.2254002,-16.892362,-13.440691)"><rect
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:0.529167;stroke-dasharray:none"
id="rect2375"
width="108.62554"
height="97.809959"
x="14.746868"
y="17.337889"
ry="6.1224627"
rx="6.1224627" /><path
id="rect1507"
style="fill:#0d9488;fill-opacity:1;stroke:none;stroke-width:2"
d="m 113.58161,108.95202 c 3.04931,0 5.50406,-2.45475 5.50406,-5.50405 V 26.896053 c 0,-3.04931 -2.45475,-5.50406 -5.50406,-5.50406 H 25.151343 c -3.04932,0 -5.50406,2.45475 -5.50406,5.50406 V 54.01068 c 0.43041,2.163111 3.18546,3.187798 6.98304,-0.609782 L 47.202714,28.840643 c 1.502396,-1.5024 2.269504,-1.31517 3.640088,-1.31517 h 30.835587 c 1.892956,0 3.761256,0.64778 2.204516,2.20452 L 40.649109,77.741016 c -1.975915,1.975915 -3.513223,2.428534 -5.941766,0 l -8.34677,-8.504391 c -1.90395,-1.903942 -6.29013,-2.909316 -6.71329,0.675928 v 33.535417 c 0,3.0493 2.45474,5.50405 5.50406,5.50405 z m -3.67471,-4.3682 H 42.782312 c -2.648146,0 -3.422195,-2.87147 0,-6.293672 L 104.72737,31.072977 c 5.71089,-5.710884 8.48527,-1.619534 8.48527,0 l 0.66301,69.379833 c 0,3.30292 -1.96658,4.13101 -3.96875,4.13101 z"
sodipodi:nodetypes="sssssscccsscccccsssssccccs" /></g></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
zarf/screenshots/detail.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB