I measure amount of coal in a stack of my automatic coal boiler. Measurements does OrangePI with ultrasonic sensor, and it sends data to MYSQL server. There I have a webpage, which shows me chart with 14 days history. Here I can see, how much coal I have in stack and how fast it wanes.
Chart is done by Amchart serial chart. It works nicely. Data are inline in page in JSON:
var chartdataNasypka = [{"datumcas":"2022-12-04 00:00","vyskauhli":"41"},{"datumcas":"2022-12-04 01:00","vyskauhli":"43"},.........]
(measures once an hour)
Now I had an idea, that it will be nice to see a curve of outdoor temperature-in a same chart, both values combined in one chart. I have a weather station on Raspberry PI, sending data again to MYSQL, but to another table. I tuned out a SELECT command, so I have same datetime format:
var chartdataMeteostanice = [{"datumcas":"2022-12-04 00:00","teplota":"-0.2"},{"datumcas":"2022-12-04 01:00","teplota":"0.0"},.........]
The trouble is, that both values (coal height in stack and outdoor temperature) cannot be visualised at once in one chart. It shows data from one database only, depends which from the following lines are last:
chart.dataProvider = chartdataMeteostanice;
chart.dataProvider = chartdataNasypka;
I don't know, how to specify data provider for valueAxisY2. I googled for a few hours, but found only switching charts by data sets, but this is not my case, I want to see everything without switching.
I would like to avoid merging both JSON data into one, as there may be outage of one sensor/data and it may be merged/visualised incorrectly.
So is there a way, how to solve it? I have Amcharts v3, but I can update it to the current v5, if needed.
Thank you
Code I have now:
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.pathToImages = "amcharts/images/";
chart.borderColor = "#000000";
chart.borderAlpha = 0.15;
chart.zoomOutText = "Ukaž vše";
chart.dataProvider = chartdataMeteostanice;
chart.dataProvider = chartdataNasypka;
chart.categoryField = "datumcas";
chart.dataDateFormat = "YYYY-MM-DD JJ:NN";
chart.numberFormatter = {precision:-1,decimalSeparator:"."};
var balloon = chart.balloon;
balloon.fillAlpha = 1;
balloon.cornerRadius = 2;
balloon.showBullet = true;
// AXES
// DATUM
var categoryAxis = chart.categoryAxis;
categoryAxis.parseDates = true;
categoryAxis.minPeriod = "hh";
categoryAxis.gridAlpha = 0.2;
categoryAxis.axisColor = "#DADADA";
categoryAxis.autoGridCount = true;
categoryAxis.equalSpacing = false;
categoryAxis.startOnAxis = true;
categoryAxis.centerLabels=false;
// VÝŠKA UHLÍ
var valueAxis = new AmCharts.ValueAxis();
valueAxis.axisAlpha = 1;
valueAxis.gridCount = 12;
valueAxis.autoGridCount = false;
valueAxis.gridAlpha = 0.2;
valueAxis.minimum = 0;
valueAxis.maximum = 120;
valueAxis.unit = "cm";
valueAxis.title = "Výška uhlí";
valueAxis.position = "left";
chart.addValueAxis(valueAxis);
// TEPLOTA
var valueAxisY2 = new AmCharts.ValueAxis();
valueAxisY2.axisAlpha = 1;
valueAxisY2.gridCount = 10;
valueAxisY2.gridAlpha = 0;
valueAxisY2.minimum = -20;
valueAxisY2.maximum = 20;
valueAxisY2.unit = "°C";
valueAxisY2.title = "Teplota";
valueAxisY2.autoGridCount = false;
valueAxisY2.position = "right";
chart.addValueAxis(valueAxisY2);
// GRAPH - VÝŠKA UHLÍ
var graphu = new AmCharts.AmGraph();
graphu.type = "line";
graphu.title = "Výška uhlí";
graphu.valueField = "vyskauhli";
graphu.lineAlpha = 1;
graphu.lineColor = "#502000";
graphu.fillAlphas = 0.7; // setting fillAlphas to > 0 value makes it area graph
graphu.connect = false; // když chybí hodnoty, nenapojuje
chart.addGraph(graphu);
// GRAPH - TEPLOTA
var grapht = new AmCharts.AmGraph();
grapht.type = "line";
grapht.title = "Teplota";
grapht.valueField = "teplota";
grapht.lineAlpha = 1;
grapht.lineColor = "#FF0000";
grapht.negativeLineColor = "#0080FF";
grapht.fillAlphas = 0; // setting fillAlphas to > 0 value makes it area graph
grapht.connect = false; // když chybí hodnoty, nenapojuje
grapht.bullet = "round";
grapht.bulletBorderColor = "#FFFFFF";
grapht.bulletBorderThickness = 2;
grapht.bulletBorderAlpha = 1;
grapht.lineThickness = 3;
grapht.balloonText = "<b><span style='font-size:11px;'>teplota: [[value]]°C</span></b>";
grapht.balloonAlpha = 1;
grapht.hideBulletsCount = 20; // this makes the chart to hide bullets when there are more than 50 series in selection
chart.addGraph(grapht);
// CURSOR
var chartCursor = new AmCharts.ChartCursor();
chartCursor.cursorPosition = "mouse";
chartCursor.categoryBalloonDateFormat = "JJ:NN, DD.MM.YYYY";
chart.addChartCursor(chartCursor);
// SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);
// WRITE
chart.write("chartdiv");
});
So, it seems that the best option is to merge both JSONs into one, then sort it.
Described here
Then the part of that code is:
var uhliateplota = <?
$merged_array = array_merge($datauhli, $datateplota);
// $datauhli and $datateplota holds values from SQL requests
echo json_encode($merged_array);
?>
// Sort:
uhliateplota.sort((a, b) => new Date(a.datumcas) - new Date(b.datumcas))
// datumcas means datetime
var chartdataSPOJENA = []
uhliateplota.forEach(function(e) {
if(!this[e.datumcas]) {
this[e.datumcas] = {datumcas: e.datumcas, vyskauhli: null, teplota: null}
chartdataSPOJENA.push(this[e.datumcas])
}
this[e.datumcas] = Object.assign(this[e.datumcas], e)
})
var JSONdata = (JSON.stringify(chartdataSPOJENA, 0, 4))
// document.write(JSONdata)
AmCharts.ready(function () {
// SERIAL CHART
chart = new AmCharts.AmSerialChart();
chart.pathToImages = "amcharts/images/";
chart.borderColor = "#000000";
chart.borderAlpha = 0.15;
chart.zoomOutText = "Show All";
chart.dataProvider = chartdataSPOJENA;