1. save file as json

2. modify html to show all data
3. set black as the background color of appbar
This commit is contained in:
2024-12-18 10:28:29 +08:00
parent 2a4e21fa25
commit 747180e94f
29 changed files with 278 additions and 145 deletions

View File

@@ -79,7 +79,8 @@ class _MyHomePageState extends State<MyHomePage> {
// TRY THIS: Try changing the color here to a specific color (to // TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same. // change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor:
Colors.black, //Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by // Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title. // the App.build method, and use it to set our appbar title.
title: Text(widget.title), title: Text(widget.title),
@@ -163,7 +164,7 @@ class _MyHomePageState extends State<MyHomePage> {
await methodChannel.invokeMethod('getExternalDownloadsPath'); await methodChannel.invokeMethod('getExternalDownloadsPath');
DateTime now = DateTime.now(); DateTime now = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd_HH-mm-ss').format(now); String formattedDate = DateFormat('yyyy-MM-dd_HH-mm-ss').format(now);
File file = File('$downloadsPath/$formattedDate.txt'); File file = File('$downloadsPath/$formattedDate.json');
var sink = file.openWrite(); var sink = file.openWrite();
sink.write(jsonEncode(mLightSensorEvents)); sink.write(jsonEncode(mLightSensorEvents));
await sink.flush(); await sink.flush();

15
test/Sensor_datas/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,161 +1,259 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>D3.js Multiple Line Chart</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script> <title>Line Charts with D3.js</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style> <style>
.line { .line {
fill: none; fill: none;
stroke-width: 2px; stroke-width: 2px;
} }
.axis-label {
font-size: 16px; .dot {
fill: red;
} }
.legend {
font-size: 16px; .tooltip {
position: absolute;
text-align: center;
width: auto;
padding: 5px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.line-lux {
stroke: steelblue;
}
.dot-lux {
fill: steelblue;
}
.line-lux_fast {
stroke: orange;
}
.dot-lux_fast {
fill: orange;
}
.line-lux_slow {
stroke: green;
}
.dot-lux_slow {
fill: green;
}
.line-diff {
stroke: purple;
}
.dot-diff {
fill: purple;
} }
</style> </style>
</head> </head>
<body> <body>
<input type="file" id="fileInput" /> <h1>Line Charts with D3.js</h1>
<div id="chart"></div> <input type="file" id="fileInput">
<div id="chart"></div>
<div id="chart2"></div>
<script> <script>
// Data document.getElementById('fileInput').addEventListener('change', handleFileSelect, false);
const sample_data = [
{"lux":1263.0,"timestamp":18188401,"lux_fast":1000.0,"lux_slow":900.0},
{"lux":1000.0,"timestamp":18188571,"lux_fast":1263.0,"lux_slow":1000.0},
{"lux":900.0,"timestamp":18188741,"lux_fast":1262.0,"lux_slow":1263.0}
];
function createChart(data) { function handleFileSelect(event) {
d3.select("#chart").select("svg").remove(); const file = event.target.files[0];
// Set the dimensions and margins of the graph if (!file) {
const margin = {top: 20, right: 80, bottom: 50, left: 60}; return;
const width = 600 - margin.left - margin.right; }
const height = 400 - margin.top - margin.bottom; const reader = new FileReader();
reader.onload = function (e) {
const contents = e.target.result;
const data = JSON.parse(contents);
drawChart(data);
drawChart2(data);
};
reader.readAsText(file);
}
// Append the svg object to the body of the page function drawChart(data) {
const svg = d3.select("#chart") const margin = { top: 20, right: 30, bottom: 30, left: 40 },
.append("svg") width = 800 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
d3.select("#chart").html(""); // Clear previous chart if any
const svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right) .attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom) .attr("height", height + margin.top + margin.bottom)
.append("g") .append("g")
.attr("transform", `translate(${margin.left},${margin.top})`); .attr("transform", `translate(${margin.left},${margin.top})`);
// X scale
const x = d3.scaleLinear() const x = d3.scaleLinear()
.domain(d3.extent(data, d => d.timestamp)) .domain(d3.extent(data, d => d.timestamp))
.range([0, width]); .range([0, width]);
// Y scale
const y = d3.scaleLinear() const y = d3.scaleLinear()
.domain([d3.min(data, d => Math.min(d.lux, d.lux_fast, d.lux_slow)) - 0.5, .domain([0, d3.max(data, d => Math.max(d.lux, d.lux_fast, d.lux_slow))])
d3.max(data, d => Math.max(d.lux, d.lux_fast, d.lux_slow)) + 0.5]) .nice()
.range([height, 0]); .range([height, 0]);
// Add X axis const lineLux = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.lux));
const lineLuxFast = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.lux_fast));
const lineLuxSlow = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.lux_slow));
svg.append("g") svg.append("g")
.attr("transform", `translate(0,${height})`) .attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x)); .call(d3.axisBottom(x));
// Add Y axis
svg.append("g") svg.append("g")
.call(d3.axisLeft(y)); .call(d3.axisLeft(y));
// X axis label
svg.append("text")
.attr("class", "axis-label")
.attr("text-anchor", "middle")
.attr("x", width / 2)
.attr("y", height + margin.bottom - 10)
.text("Timestamp");
// Y axis label
svg.append("text")
.attr("class", "axis-label")
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.attr("y", -margin.left + 20)
.attr("x", -height / 2)
.text("Lux Value");
// Line generator
const line = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.lux));
// Add the lux line
svg.append("path") svg.append("path")
.datum(data) .datum(data)
.attr("class", "line") .attr("class", "line line-lux")
.attr("d", line) .attr("d", lineLux);
.attr("stroke", "blue");
// Add the lux_fast
svg.append("path") svg.append("path")
.datum(data) .datum(data)
.attr("class", "line") .attr("class", "line line-lux_fast")
.attr("d", d3.line() .attr("d", lineLuxFast);
.x(d => x(d.timestamp))
.y(d => y(d.lux_fast)))
.attr("stroke", "red");
// Add the lux_slow line
svg.append("path") svg.append("path")
.datum(data) .datum(data)
.attr("class", "line") .attr("class", "line line-lux_slow")
.attr("d", d3.line() .attr("d", lineLuxSlow);
.x(d => x(d.timestamp))
.y(d => y(d.lux_slow)))
.attr("stroke", "green");
// Add legend // Add dots for lux
const legend = svg.append("g") svg.selectAll(".dot-lux")
.attr("class", "legend") .data(data)
.attr("transform", `translate(${width + 10}, 0)`); .enter().append("circle")
.attr("class", "dot dot-lux")
.attr("cx", d => x(d.timestamp))
.attr("cy", d => y(d.lux))
.attr("r", 3)
.on("mouseover", function (event, d) {
const tooltip = d3.select("body").append("div").attr("class", "tooltip");
tooltip.html(`timestamp: ${d.timestamp}<br>lux: ${d.lux}`)
.style("left", (event.pageX + 5) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function () {
d3.select(".tooltip").remove();
});
const legendItems = [ // Add dots for lux_fast
{ label: "Lux", color: "blue" }, svg.selectAll(".dot-lux_fast")
{ label: "Lux Fast", color: "red" }, .data(data)
{ label: "Lux Slow", color: "green" } .enter().append("circle")
]; .attr("class", "dot dot-lux_fast")
.attr("cx", d => x(d.timestamp))
.attr("cy", d => y(d.lux_fast))
.attr("r", 3)
.on("mouseover", function (event, d) {
const tooltip = d3.select("body").append("div").attr("class", "tooltip");
tooltip.html(`timestamp: ${d.timestamp}<br>lux_fast: ${d.lux_fast}`)
.style("left", (event.pageX + 5) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function () {
d3.select(".tooltip").remove();
});
legendItems.forEach((item, index) => { // Add dots for lux_slow
const legendItem = legend.append("g") svg.selectAll(".dot-lux_slow")
.attr("transform", `translate(0, ${index * 20})`); .data(data)
.enter().append("circle")
legendItem.append("rect") .attr("class", "dot dot-lux_slow")
.attr("width", 10) .attr("cx", d => x(d.timestamp))
.attr("height", 10) .attr("cy", d => y(d.lux_slow))
.attr("fill", item.color); .attr("r", 3)
.on("mouseover", function (event, d) {
legendItem.append("text") const tooltip = d3.select("body").append("div").attr("class", "tooltip");
.attr("x", 15) tooltip.html(`timestamp: ${d.timestamp}<br>lux_slow: ${d.lux_slow}`)
.attr("y", 10) .style("left", (event.pageX + 5) + "px")
.text(item.label); .style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function () {
d3.select(".tooltip").remove();
}); });
} }
// File input event listener
document.getElementById('fileInput').addEventListener('change', function(e) { function drawChart2(data) {
const file = e.target.files[0]; const margin = { top: 20, right: 30, bottom: 30, left: 40 },
if (file) { width = 800 - margin.left - margin.right,
const reader = new FileReader(); height = 400 - margin.top - margin.bottom;
reader.onload = function(e) {
const contents = e.target.result; d3.select("#chart2").html(""); // Clear previous chart if any
try {
const data = JSON.parse(contents); const svg = d3.select("#chart2").append("svg")
createChart(data); .attr("width", width + margin.left + margin.right)
} catch (error) { .attr("height", height + margin.top + margin.bottom)
console.error("Error parsing JSON:", error); .append("g")
alert("Error parsing JSON file. Please make sure it's a valid JSON."); .attr("transform", `translate(${margin.left},${margin.top})`);
}
}; const x = d3.scaleLinear()
reader.readAsText(file); .domain(d3.extent(data, d => d.timestamp))
} .range([0, width]);
const y = d3.scaleLinear()
.domain([d3.min(data, d => d.lux - d.lux_slow), d3.max(data, d => d.lux - d.lux_slow)])
.nice()
.range([height, 0]);
const lineDiff = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d.lux - d.lux_slow));
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
svg.append("path")
.datum(data)
.attr("class", "line line-diff")
.attr("d", lineDiff);
// Add dots for lux - lux_slow
svg.selectAll(".dot-diff")
.data(data)
.enter().append("circle")
.attr("class", "dot dot-diff")
.attr("cx", d => x(d.timestamp))
.attr("cy", d => y(d.lux - d.lux_slow))
.attr("r", 3)
.on("mouseover", function (event, d) {
const tooltip = d3.select("body").append("div").attr("class", "tooltip");
tooltip.html(`timestamp: ${d.timestamp}<br>lux - lux_slow: ${d.lux - d.lux_slow}`)
.style("left", (event.pageX + 5) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function () {
d3.select(".tooltip").remove();
}); });
createChart(sample_data); }
</script> </script>
</body> </body>
</html> </html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long