feat: Add new application events and update system state management

This commit is contained in:
Miguel 2025-08-14 13:31:09 +02:00
parent 087a9458ce
commit d6190f3323
4 changed files with 222 additions and 230 deletions

View File

@ -450,8 +450,44 @@
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-14T13:26:50.126159",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-14T13:26:50.175938",
"level": "info",
"event_type": "dataset_activated",
"message": "Dataset activated: DAR",
"details": {
"dataset_id": "DAR",
"variables_count": 2,
"streaming_count": 2,
"prefix": "gateway_phoenix"
}
},
{
"timestamp": "2025-08-14T13:26:50.178048",
"level": "info",
"event_type": "csv_recording_started",
"message": "CSV recording started: 1 datasets activated",
"details": {
"activated_datasets": 1,
"total_datasets": 3
}
},
{
"timestamp": "2025-08-14T13:26:50.239908",
"level": "error",
"event_type": "csv_cleanup_failed",
"message": "CSV cleanup failed: 'max_hours'",
"details": {}
}
],
"last_updated": "2025-08-14T13:10:18.671577",
"total_entries": 41
"last_updated": "2025-08-14T13:26:50.239908",
"total_entries": 45
}

View File

@ -2,12 +2,7 @@ import React from 'react'
import recLogo from './assets/logo/record.png'
import { Routes, Route, Link } from 'react-router-dom'
import { Box, Container, Flex, HStack, Select, Button, Heading, Text, useColorMode, useColorModeValue, Stack } from '@chakra-ui/react'
import EventsPage from './pages/Events.jsx'
import ConfigPage from './pages/Config.jsx'
import PlotsPage from './pages/Plots.jsx'
import PLCConfigModal from './components/PLCConfigModal.jsx'
import DashboardPage from './pages/DashboardNew.jsx'
import DatasetManager from './components/DatasetManager.jsx'
function Home() {
return (
@ -85,10 +80,6 @@ function NavBar() {
<Heading as="span" size="sm">PLC Streamer</Heading>
</HStack>
<HStack spacing={2}>
<Button as={Link} to="/datasets" size="sm" variant="outline">📊 Datasets</Button>
<Button as={Link} to="/events" size="sm" variant="outline">Events</Button>
<Button as={Link} to="/config" size="sm" variant="outline">Config</Button>
<Button as={Link} to="/plots" size="sm" variant="outline">📈 Plots</Button>
<ColorModeSelector />
</HStack>
</Flex>
@ -104,10 +95,7 @@ function App() {
<NavBar />
<Routes>
<Route path="/" element={<DashboardPage />} />
<Route path="/datasets" element={<DatasetManager />} />
<Route path="/events" element={<EventsPage />} />
<Route path="/config" element={<ConfigPage />} />
<Route path="/plots" element={<PlotsPage />} />
<Route path="/*" element={<DashboardPage />} />
</Routes>
</Box>
)

View File

@ -4,11 +4,6 @@ import {
Container,
VStack,
Heading,
Tabs,
TabList,
TabPanels,
Tab,
TabPanel,
Card,
CardBody,
CardHeader,
@ -455,188 +450,176 @@ function DatasetManager() {
</Button>
</Flex>
<Tabs variant="enclosed" colorScheme="blue">
<TabList>
<Tab>📋 Dataset Definitions</Tab>
<Tab> Dataset Variables</Tab>
</TabList>
{/* Dataset Definitions Section */}
{datasetsSchemaData?.schema && datasetsConfig && (
<Card>
<CardHeader>
<Heading size="md">📋 Dataset Metadata Configuration</Heading>
<Text fontSize="sm" color="gray.500" mt={1}>
Configure dataset names, prefixes, sampling intervals and enable/disable datasets
</Text>
</CardHeader>
<CardBody>
<Form
schema={datasetsSchemaData.schema}
uiSchema={datasetsSchemaData.uiSchema}
formData={datasetsConfig}
validator={validator}
widgets={allWidgets}
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
onSubmit={({ formData }) => saveDatasets(formData)}
onChange={({ formData }) => setDatasetsConfig(formData)}
>
<HStack spacing={2} mt={4}>
<Button type="submit" colorScheme="blue">
💾 Save Definitions
</Button>
<Button variant="outline" onClick={loadDatasetData}>
🔄 Reset
</Button>
</HStack>
</Form>
</CardBody>
</Card>
)}
<TabPanels>
<TabPanel p={0} pt={4}>
{datasetsSchemaData?.schema && datasetsConfig && (
<Card>
<CardHeader>
<Heading size="md">Dataset Metadata Configuration</Heading>
<Text fontSize="sm" color="gray.500" mt={1}>
Configure dataset names, prefixes, sampling intervals and enable/disable datasets
</Text>
</CardHeader>
<CardBody>
<Form
schema={datasetsSchemaData.schema}
uiSchema={datasetsSchemaData.uiSchema}
formData={datasetsConfig}
validator={validator}
widgets={allWidgets}
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
onSubmit={({ formData }) => saveDatasets(formData)}
onChange={({ formData }) => setDatasetsConfig(formData)}
>
<HStack spacing={2} mt={4}>
<Button type="submit" colorScheme="blue">
💾 Save Definitions
</Button>
<Button variant="outline" onClick={loadDatasetData}>
🔄 Reset
</Button>
</HStack>
</Form>
</CardBody>
</Card>
)}
</TabPanel>
<TabPanel p={0} pt={4}>
{/* Dataset Variables Configuration with Combo Selector */}
<Card>
<CardHeader>
<Heading size="md">Dataset Variables Configuration</Heading>
<Text fontSize="sm" color="gray.500" mt={1}>
Select a dataset, then configure its PLC variables and streaming settings
{/* Dataset Variables Configuration Section */}
<Card>
<CardHeader>
<Heading size="md"> Dataset Variables Configuration</Heading>
<Text fontSize="sm" color="gray.500" mt={1}>
Select a dataset, then configure its PLC variables and streaming settings
</Text>
</CardHeader>
<CardBody>
{/* Step 1: Dataset Selector (Combo) */}
<VStack spacing={4} align="stretch">
<Box>
<Text fontSize="sm" fontWeight="bold" mb={2}>
🎯 Select Dataset
</Text>
<Select
value={selectedDatasetId}
onChange={(e) => setSelectedDatasetId(e.target.value)}
placeholder="Choose a dataset to configure..."
size="md"
>
{availableDatasets.map(dataset => (
<option key={dataset.id} value={dataset.id}>
📊 {dataset.name} ({dataset.id})
</option>
))}
</Select>
{availableDatasets.length === 0 && (
<Text fontSize="sm" color="orange.500" mt={2}>
No datasets available. Configure datasets first in the "Dataset Definitions" section above.
</Text>
</CardHeader>
<CardBody>
{/* Step 1: Dataset Selector (Combo) */}
<VStack spacing={4} align="stretch">
<Box>
<Text fontSize="sm" fontWeight="bold" mb={2}>
🎯 Select Dataset
</Text>
<Select
value={selectedDatasetId}
onChange={(e) => setSelectedDatasetId(e.target.value)}
placeholder="Choose a dataset to configure..."
size="md"
>
{availableDatasets.map(dataset => (
<option key={dataset.id} value={dataset.id}>
📊 {dataset.name} ({dataset.id})
</option>
))}
</Select>
{availableDatasets.length === 0 && (
<Text fontSize="sm" color="orange.500" mt={2}>
No datasets available. Configure datasets first in the "Dataset Definitions" tab.
</Text>
)}
</Box>
)}
</Box>
{/* Variables Configuration Form */}
{selectedDatasetId && (
<Box>
<Divider mb={4} />
<Text fontSize="sm" fontWeight="bold" mb={2}>
Configure Variables for Dataset "{selectedDatasetId}"
</Text>
{/* Simplified schema for selected dataset variables */}
{(() => {
const selectedDatasetVars = getSelectedDatasetVariables()
// Schema for this dataset's variables
const singleDatasetSchema = {
{/* Variables Configuration Form */}
{selectedDatasetId && (
<Box>
<Divider mb={4} />
<Text fontSize="sm" fontWeight="bold" mb={2}>
Configure Variables for Dataset "{selectedDatasetId}"
</Text>
{/* Simplified schema for selected dataset variables */}
{(() => {
const selectedDatasetVars = getSelectedDatasetVariables()
// Schema for this dataset's variables
const singleDatasetSchema = {
type: "object",
properties: {
variables: {
type: "array",
title: "Variables",
description: `PLC variables to record in dataset ${selectedDatasetId}`,
items: {
type: "object",
properties: {
variables: {
type: "array",
title: "Variables",
description: `PLC variables to record in dataset ${selectedDatasetId}`,
items: {
type: "object",
properties: {
name: { type: "string", title: "Variable Name" },
area: {
type: "string",
title: "Memory Area",
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
default: "db"
},
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
type: {
type: "string",
title: "Data Type",
enum: ["real", "int", "dint", "bool", "word", "byte"],
default: "real"
},
streaming: { type: "boolean", title: "Stream to UDP", default: false }
},
required: ["name", "area", "offset", "type"]
}
}
}
name: { type: "string", title: "Variable Name" },
area: {
type: "string",
title: "Memory Area",
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
default: "db"
},
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
type: {
type: "string",
title: "Data Type",
enum: ["real", "int", "dint", "bool", "word", "byte"],
default: "real"
},
streaming: { type: "boolean", title: "Stream to UDP", default: false }
},
required: ["name", "area", "offset", "type"]
}
}
}
}
const singleDatasetUiSchema = {
variables: {
items: {
"ui:layout": [[
{ "name": "name", "width": 3 },
{ "name": "area", "width": 2 },
{ "name": "db", "width": 1 },
{ "name": "offset", "width": 2 },
{ "name": "type", "width": 2 },
{ "name": "streaming", "width": 2 }
]]
}
}
}
const singleDatasetUiSchema = {
variables: {
items: {
"ui:layout": [[
{ "name": "name", "width": 3 },
{ "name": "area", "width": 2 },
{ "name": "db", "width": 1 },
{ "name": "offset", "width": 2 },
{ "name": "type", "width": 2 },
{ "name": "streaming", "width": 2 }
]]
}
}
}
return (
<Form
schema={singleDatasetSchema}
uiSchema={singleDatasetUiSchema}
formData={selectedDatasetVars}
validator={validator}
widgets={allWidgets}
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
onSubmit={({ formData }) => {
updateSelectedDatasetVariables(formData)
saveVariables(variablesConfig).then(() => {
// Additional trigger after successful save
triggerVariableRefresh()
})
}}
onChange={({ formData }) => updateSelectedDatasetVariables(formData)}
>
<HStack spacing={2} mt={4}>
<Button type="submit" colorScheme="blue">
💾 Save Variables for {selectedDatasetId}
</Button>
<Button variant="outline" onClick={loadDatasetData}>
🔄 Reset
</Button>
</HStack>
</Form>
)
})()}
</Box>
)}
return (
<Form
schema={singleDatasetSchema}
uiSchema={singleDatasetUiSchema}
formData={selectedDatasetVars}
validator={validator}
widgets={allWidgets}
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
onSubmit={({ formData }) => {
updateSelectedDatasetVariables(formData)
saveVariables(variablesConfig).then(() => {
// Additional trigger after successful save
triggerVariableRefresh()
})
}}
onChange={({ formData }) => updateSelectedDatasetVariables(formData)}
>
<HStack spacing={2} mt={4}>
<Button type="submit" colorScheme="blue">
💾 Save Variables for {selectedDatasetId}
</Button>
<Button variant="outline" onClick={loadDatasetData}>
🔄 Reset
</Button>
</HStack>
</Form>
)
})()}
</Box>
)}
{!selectedDatasetId && availableDatasets.length > 0 && (
<Box textAlign="center" py={8}>
<Text color="gray.500">
👆 Select a dataset above to configure its variables
</Text>
</Box>
)}
</VStack>
</CardBody>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
{!selectedDatasetId && availableDatasets.length > 0 && (
<Box textAlign="center" py={8}>
<Text color="gray.500">
👆 Select a dataset above to configure its variables
</Text>
</Box>
)}
</VStack>
</CardBody>
</Card>
</VStack>
)
}
@ -853,43 +836,28 @@ function DashboardContent() {
<StatusBar status={status} onRefresh={loadStatus} />
<Tabs variant="enclosed" colorScheme="blue">
<TabList>
<Tab>🔧 Configuration</Tab>
<Tab>📊 Datasets</Tab>
<Tab>📈 Plotting</Tab>
<Tab>📋 Events</Tab>
</TabList>
{/* Configuration Panel */}
<ConfigurationPanel
schemaData={schemaData}
formData={formData}
onFormChange={setFormData}
onSave={saveConfig}
saving={saving}
message={message}
/>
<TabPanels>
<TabPanel p={0} pt={4}>
<ConfigurationPanel
schemaData={schemaData}
formData={formData}
onFormChange={setFormData}
onSave={saveConfig}
saving={saving}
message={message}
/>
</TabPanel>
{/* Dataset Management */}
<DatasetManager />
<TabPanel p={0} pt={4}>
<DatasetManager />
</TabPanel>
{/* Plot Management */}
<PlotManager />
<TabPanel p={0} pt={4}>
<PlotManager />
</TabPanel>
<TabPanel p={0} pt={4}>
<EventsDisplay
events={events}
loading={eventsLoading}
onRefresh={loadEvents}
/>
</TabPanel>
</TabPanels>
</Tabs>
{/* Events Display */}
<EventsDisplay
events={events}
loading={eventsLoading}
onRefresh={loadEvents}
/>
</VStack>
</Container>
)

View File

@ -4,10 +4,10 @@
"should_stream": false,
"active_datasets": [
"DAR",
"Test",
"Fast"
"Fast",
"Test"
]
},
"auto_recovery_enabled": true,
"last_update": "2025-08-14T13:09:58.767138"
"last_update": "2025-08-14T13:26:50.179055"
}