Added axios requests to show the nodes from the database, added calculator for battery level and input field for la and lo

This commit is contained in:
Mikail Killi 2024-10-14 20:20:49 +02:00
parent fe65349b54
commit b2f6f216f6
4 changed files with 47 additions and 63 deletions

View file

@ -17,6 +17,6 @@ body:json {
"coord_lo":2, "coord_lo":2,
"battery_minimum":3, "battery_minimum":3,
"battery_maximum":4, "battery_maximum":4,
"group":"20abe318-7238-4f63-908f-a484955ee3bc" "group":"54eccfb5-1d5a-4cad-a1a2-468eca68ffd6"
} }
} }

View file

@ -18,11 +18,11 @@
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
<span class="mr-2">Coordinates:</span> <span class="mr-2">Coordinates:</span>
<span>La: {{ node.coordla }}, Long: {{ node.coordlong }}</span> <span>La: {{ node.coord_la }}, Long: {{ node.coord_lo }}</span>
</div> </div>
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
<span class="mr-2">Temperature:</span> <span class="mr-2">Temperature:</span>
<span>{{ sensorData?.temperature }}°C</span> <span>{{ sensorData?.temperature !== undefined ? sensorData.temperature : 'NaN' }}°C</span>
</div> </div>
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
<span class="mr-2">Battery Voltage:</span> <span class="mr-2">Battery Voltage:</span>
@ -30,7 +30,7 @@
</div> </div>
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
<span class="mr-2">Runtime:</span> <span class="mr-2">Runtime:</span>
<span>{{ sensorData?.uptime }} hours</span> <span>{{ sensorData?.uptime ? (sensorData.uptime / 3600).toFixed(2) + ' hours' : 'N/A' }}</span>
</div> </div>
</div> </div>
</v-expansion-panel-text> </v-expansion-panel-text>
@ -62,24 +62,10 @@ watch([searching, visibleIds], ([searching, visibleIds]) => {
onMounted(async () => { onMounted(async () => {
try { try {
const { data } = await axios.get<SensorData>( const { data } = await axios.get<SensorData>(
`http://localhost:8080/api/v1/data?nodeId=${props.node.id}` `http://localhost:8080/api/v1/data?id=${props.node.id}`
); );
sensorData.value = data; sensorData.value = data;
} catch (error) { } catch (error) {
console.error("Error fetching sensor data:", error); console.error("Error fetching sensor data:", error);
} }
}); });
</script>
<style scoped>
.values {
display: flex;
align-items: center;
}
.v-text-field {
max-width: 200px;
width: 100%;
}
</style>

View file

@ -14,21 +14,21 @@
</thead> </thead>
<tbody> <tbody>
<tr v-for="(node, index) in tableData" :key="index"> <tr v-for="(node, index) in tableData" :key="index">
<td>{{ node.name }}</td> <td>{{ node.id }}</td>
<td> <td>
<span :class="node.sensorData.voltage ? 'status-online' : 'status-offline'"> <span :class="node.sensorData.voltage !== 'N/A' ? 'status-online' : 'status-offline'">
{{ node.sensorData.voltage ? 'ONLINE' : 'OFFLINE' }} {{ node.sensorData.voltage !== 'N/A' ? 'ONLINE' : 'OFFLINE' }}
</span> </span>
</td> </td>
<td <td
contenteditable="true" contenteditable="true"
@blur="validateAndUpdateLatLng(node, 'coordla', $event)" @blur="validateAndUpdateLatLng(node, 'coord_la', $event)"
>{{ node.coordla }}</td> >{{ node.coord_la }}</td>
<td <td
contenteditable="true" contenteditable="true"
@blur="validateAndUpdateLatLng(node, 'coordlong', $event)" @blur="validateAndUpdateLatLng(node, 'coord_lo', $event)"
>{{ node.coordlong }}</td> >{{ node.coord_lo }}</td>
<td>{{ calculateBatteryPercentage(node.sensorData.voltage, node.batteryMinimum, node.batteryMaximum) }}%</td> <td>{{ calculateBatteryPercentage(node.sensorData.voltage, node.battery_minimum, node.battery_maximum) }}%</td>
<td>{{ node.sensorData.temperature }}°C</td> <td>{{ node.sensorData.temperature }}°C</td>
<td>{{ formatRuntime(node.sensorData.uptime) }}</td> <td>{{ formatRuntime(node.sensorData.uptime) }}</td>
</tr> </tr>
@ -52,17 +52,20 @@ export default {
methods: { methods: {
async fetchNodesAndData() { async fetchNodesAndData() {
try { try {
const nodesResponse = await axios.get('http://localhost:8080/api/v1/nodes'); const nodeGroupsResponse = await axios.get('http://localhost:8080/api/v1/nodes');
const nodes = nodesResponse.data; const nodeGroups = nodeGroupsResponse.data;
const nodes = nodeGroups.flatMap(group => group.node);
const sensorDataResponse = await axios.get('http://localhost:8080/api/v1/data'); const sensorDataResponse = await axios.get('http://localhost:8080/api/v1/data');
const sensorData = sensorDataResponse.data; const sensorDataArray = sensorDataResponse.data;
this.tableData = nodes.map(node => {
const nodeSensorData = sensorDataArray.find(data => data.node.id === node.id);
this.tableData = nodes.map((node) => {
const nodeSensorData = sensorData.find((data) => data.id === node.id);
return { return {
...node, ...node,
sensorData: nodeSensorData || { sensorData: nodeSensorData ? nodeSensorData.sensor_data : {
temperature: 'N/A', temperature: 'N/A',
voltage: 'N/A', voltage: 'N/A',
uptime: 'N/A', uptime: 'N/A',
@ -92,22 +95,16 @@ export default {
const originalValue = node[field]; const originalValue = node[field];
let newValue = event.target.innerText; let newValue = event.target.innerText;
// Normalize separated values
newValue = newValue.replace(',', '.'); newValue = newValue.replace(',', '.');
// Check if it's a valid float value
const validNumberRegex = /^-?\d+(\.\d+)?$/; const validNumberRegex = /^-?\d+(\.\d+)?$/;
if (validNumberRegex.test(newValue)) { if (validNumberRegex.test(newValue)) {
const parsedValue = parseFloat(newValue); const parsedValue = parseFloat(newValue);
// Update if valid
node[field] = parsedValue; node[field] = parsedValue;
console.log(`Updated ${field} of ${node.name}: ${parsedValue}`); console.log(`Updated ${field} of ${node.id}: ${parsedValue}`);
} else { } else {
// Reset to original value if invalid
event.target.innerText = originalValue; event.target.innerText = originalValue;
console.log(`Failed to set ${field} of ${node.name}: Invalid input "${newValue}"`); console.log(`Failed to set ${field} of ${node.id}: Invalid input "${newValue}"`);
} }
}, },
}, },
@ -115,7 +112,6 @@ export default {
</script> </script>
<style scoped> <style scoped>
/* Styling remains the same */
.table-container { .table-container {
background-color: white; background-color: white;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;

View file

@ -1,15 +1,17 @@
export interface Node { export interface Node {
id: string; id: string;
coordla: number; coord_la: number;
coordlong: number; coord_lo: number;
batteryMinimum: number; battery_minimum: number;
batteryMaximum: number; battery_maximum: number;
group: string; group: string;
sensorData: SensorData[];
} }
export interface NodeGroup { export interface NodeGroup {
id: string; id: string;
name: string; name: string;
node: Node[];
} }
export interface SensorData { export interface SensorData {