HTML Elements

This commit is contained in:
root 2024-01-04 04:56:08 +00:00
parent cc7dde4f56
commit 50ce057dc7
9 changed files with 589 additions and 12 deletions

View File

@ -1267,3 +1267,209 @@ Date;Time;Timestamp;PM2_5(ug/m3);AQI(US);AQI(CN);PM10(ug/m3);PM1(ug/m3);Outdoor
2024/01/03;23:07:27;1704323247;18.0;63;26;21.0;14.0;1;1;25.2;77.3;51;970;
2024/01/03;23:12:27;1704323547;16.0;59;23;18.0;12.0;72;31;25.1;77.3;51;966;
2024/01/03;23:17:27;1704323847;17.0;61;24;20.0;13.0;76;34;25.0;77.1;51;959;
2024/01/03;23:22:27;1704324147;17.0;61;24;19.0;13.0;75;34;25.0;77.0;51;959;
2024/01/03;23:27:27;1704324447;16.0;59;23;20.0;12.0;75;34;25.0;77.0;51;944;
2024/01/03;23:32:27;1704324747;15.0;57;21;16.0;11.0;75;34;25.0;77.0;51;917;
2024/01/03;23:37:27;1704325047;18.0;63;26;21.0;14.0;76;34;24.9;76.9;53;895;
2024/01/03;23:42:27;1704325347;20.0;68;29;23.0;16.0;72;31;24.9;76.9;54;912;
2024/01/03;23:47:27;1704325647;19.0;66;27;23.0;15.0;73;32;25.0;77.1;57;921;
2024/01/03;23:52:27;1704325947;18.0;63;26;20.0;14.0;76;34;25.2;77.3;59;945;
2024/01/03;23:57:25;1704326245;18.0;63;26;27.0;14.0;74;33;25.3;77.5;62;960;
2024/01/03;23:57:27;1704326247;18.0;63;26;27.0;14.0;74;33;25.3;77.5;62;960;
2024/01/03;23:57:35;1704326255;19.0;66;27;25.0;16.0;74;33;25.3;77.5;62;962;
2024/01/03;23:57:45;1704326265;19.0;66;27;24.0;16.0;74;33;25.3;77.5;62;963;
2024/01/03;23:57:55;1704326275;19.0;66;27;22.0;16.0;74;33;25.3;77.5;62;963;
2024/01/03;23:58:05;1704326285;20.0;68;29;23.0;17.0;74;33;25.2;77.4;63;963;
2024/01/03;23:58:15;1704326295;19.0;66;27;21.0;16.0;74;33;25.2;77.4;63;965;
2024/01/03;23:58:25;1704326305;18.0;63;26;21.0;15.0;74;33;25.2;77.4;63;966;
2024/01/03;23:58:35;1704326315;18.0;63;26;21.0;15.0;74;33;25.2;77.3;63;965;
2024/01/03;23:58:45;1704326325;17.0;61;24;20.0;13.0;74;33;25.2;77.3;63;965;
2024/01/03;23:58:55;1704326335;18.0;63;26;20.0;15.0;74;33;25.2;77.3;63;965;
2024/01/03;23:59:05;1704326345;19.0;66;27;21.0;16.0;74;33;25.2;77.3;63;965;
2024/01/03;23:59:15;1704326355;20.0;68;29;22.0;17.0;74;33;25.2;77.3;63;965;
2024/01/03;23:59:25;1704326365;19.0;66;27;21.0;16.0;74;33;25.2;77.3;63;965;
2024/01/03;23:59:35;1704326375;19.0;66;27;20.0;16.0;77;35;25.1;77.2;63;964;
2024/01/03;23:59:45;1704326385;18.0;63;26;20.0;15.0;77;35;25.1;77.2;63;964;
2024/01/03;23:59:55;1704326395;18.0;63;26;21.0;15.0;77;35;25.1;77.2;63;965;
2024/01/04;00:00:05;1704326405;18.0;63;26;21.0;15.0;77;35;25.1;77.2;63;965;
2024/01/04;00:00:15;1704326415;19.0;66;27;22.0;16.0;77;35;25.1;77.2;63;965;
2024/01/04;00:00:25;1704326425;19.0;66;27;22.0;16.0;77;35;25.1;77.2;63;965;
2024/01/04;00:00:35;1704326435;20.0;68;29;23.0;17.0;1;1;25.1;77.2;63;966;
2024/01/04;00:00:45;1704326445;20.0;68;29;23.0;17.0;1;1;25.1;77.2;63;966;
2024/01/04;00:00:55;1704326455;20.0;68;29;22.0;17.0;1;1;25.1;77.2;63;966;
2024/01/04;00:01:05;1704326465;19.0;66;27;21.0;16.0;1;1;25.1;77.1;64;966;
2024/01/04;00:01:15;1704326475;17.0;61;24;19.0;14.0;1;1;25.1;77.1;64;966;
2024/01/04;00:01:25;1704326485;17.0;61;24;19.0;14.0;1;1;25.1;77.1;64;966;
2024/01/04;00:01:35;1704326495;19.0;66;27;21.0;16.0;1;1;25.1;77.1;64;967;
2024/01/04;00:01:45;1704326505;19.0;66;27;22.0;16.0;1;1;25.1;77.1;64;968;
2024/01/04;00:01:55;1704326515;19.0;66;27;22.0;16.0;1;1;25.1;77.1;64;969;
2024/01/04;00:02:05;1704326525;17.0;61;24;20.0;14.0;1;1;25.1;77.1;64;969;
2024/01/04;00:02:15;1704326535;17.0;61;24;20.0;14.0;1;1;25.1;77.1;64;967;
2024/01/04;00:02:25;1704326545;18.0;63;26;21.0;15.0;1;1;25.1;77.1;64;966;
2024/01/04;00:02:35;1704326555;18.0;63;26;21.0;15.0;1;1;25.1;77.1;64;966;
2024/01/04;00:02:45;1704326565;18.0;63;26;21.0;15.0;1;1;25.1;77.1;64;966;
2024/01/04;00:02:55;1704326575;18.0;63;26;21.0;15.0;1;1;25.1;77.1;64;966;
2024/01/04;00:03:05;1704326585;17.0;61;24;20.0;14.0;1;1;25.0;77.1;64;966;
2024/01/04;00:03:15;1704326595;17.0;61;24;21.0;14.0;1;1;25.0;77.1;64;966;
2024/01/04;00:03:25;1704326605;16.0;59;23;20.0;12.0;1;1;25.0;77.1;64;967;
2024/01/04;00:03:35;1704326615;17.0;61;24;21.0;14.0;1;1;25.1;77.1;64;967;
2024/01/04;00:03:45;1704326625;17.0;61;24;22.0;14.0;1;1;25.1;77.1;64;967;
2024/01/04;00:03:55;1704326635;17.0;61;24;21.0;14.0;1;1;25.1;77.1;64;967;
2024/01/04;00:04:05;1704326645;17.0;61;24;20.0;14.0;1;1;25.1;77.2;64;967;
2024/01/04;00:04:15;1704326655;17.0;61;24;20.0;14.0;1;1;25.1;77.2;64;968;
2024/01/04;00:04:25;1704326665;17.0;61;24;19.0;14.0;1;1;25.1;77.2;64;968;
2024/01/04;00:04:35;1704326675;16.0;59;23;19.0;12.0;74;33;25.1;77.1;64;968;
2024/01/04;00:04:45;1704326685;17.0;61;24;20.0;14.0;74;33;25.1;77.1;64;968;
2024/01/04;00:04:55;1704326695;17.0;61;24;20.0;14.0;74;33;25.1;77.1;64;968;
2024/01/04;00:05:05;1704326705;18.0;63;26;20.0;15.0;74;33;25.1;77.1;64;969;
2024/01/04;00:05:15;1704326715;17.0;61;24;18.0;14.0;74;33;25.1;77.1;64;970;
2024/01/04;00:05:25;1704326725;17.0;61;24;19.0;14.0;74;33;25.1;77.1;64;971;
2024/01/04;00:05:35;1704326735;17.0;61;24;19.0;14.0;74;33;25.1;77.1;64;971;
2024/01/04;00:05:45;1704326745;17.0;61;24;20.0;14.0;74;33;25.1;77.1;64;971;
2024/01/04;00:05:55;1704326755;17.0;61;24;19.0;14.0;74;33;25.1;77.1;64;971;
2024/01/04;00:06:05;1704326765;17.0;61;24;20.0;14.0;74;33;25.1;77.2;64;971;
2024/01/04;00:06:15;1704326775;18.0;63;26;21.0;15.0;74;33;25.1;77.2;64;972;
2024/01/04;00:06:25;1704326785;18.0;63;26;21.0;15.0;74;33;25.1;77.2;64;974;
2024/01/04;00:06:35;1704326795;19.0;66;27;22.0;16.0;74;33;25.1;77.1;64;975;
2024/01/04;00:06:45;1704326805;18.0;63;26;21.0;15.0;74;33;25.1;77.1;64;978;
2024/01/04;00:06:55;1704326815;18.0;63;26;20.0;15.0;74;33;25.1;77.1;64;978;
2024/01/04;00:07:05;1704326825;17.0;61;24;19.0;14.0;74;33;25.1;77.2;64;979;
2024/01/04;00:07:15;1704326835;17.0;61;24;18.0;14.0;74;33;25.1;77.2;64;980;
2024/01/04;00:07:25;1704326845;17.0;61;24;18.0;14.0;74;33;25.1;77.2;64;983;
2024/01/04;00:12:28;1704327148;17.0;61;24;18.0;13.0;74;33;25.1;77.1;64;990;
2024/01/04;00:17:28;1704327448;18.0;63;26;20.0;14.0;74;33;25.0;77.0;62;1004;
2024/01/04;00:22:28;1704327748;17.0;61;24;19.0;13.0;74;33;24.9;76.8;59;1009;
2024/01/04;00:27:28;1704328048;17.0;61;24;19.0;14.0;74;33;24.8;76.7;58;1015;
2024/01/04;00:32:28;1704328348;18.0;63;26;19.0;14.0;74;33;24.8;76.6;57;1031;
2024/01/04;00:37:28;1704328648;17.0;61;24;20.0;13.0;76;34;24.7;76.5;55;1034;
2024/01/04;00:42:28;1704328948;16.0;59;23;19.0;12.0;74;33;24.7;76.4;55;1036;
2024/01/04;00:47:28;1704329248;18.0;63;26;20.0;14.0;73;32;24.6;76.3;55;1038;
2024/01/04;00:52:28;1704329548;16.0;59;23;18.0;12.0;71;31;24.6;76.2;55;1036;
2024/01/04;00:57:28;1704329848;16.0;59;23;18.0;12.0;70;30;24.5;76.1;55;1036;
2024/01/04;01:02:28;1704330148;19.0;66;27;21.0;15.0;73;32;24.5;76.1;55;1036;
2024/01/04;01:07:28;1704330448;17.0;61;24;21.0;13.0;1;1;24.6;76.3;54;1042;
2024/01/04;01:12:28;1704330748;17.0;61;24;20.0;13.0;72;31;25.0;76.9;54;1091;
2024/01/04;01:17:28;1704331048;16.0;59;23;18.0;12.0;71;31;25.7;78.3;53;1075;
2024/01/04;01:22:28;1704331348;16.0;59;23;19.0;12.0;69;29;26.7;80.0;53;1077;
2024/01/04;01:27:28;1704331648;17.0;61;24;19.0;13.0;70;30;27.6;81.7;53;1088;
2024/01/04;01:32:28;1704331948;16.0;59;23;19.0;13.0;70;30;28.5;83.3;53;1086;
2024/01/04;01:37:28;1704332248;17.0;61;24;19.0;14.0;70;30;29.2;84.6;51;1090;
2024/01/04;01:42:28;1704332548;18.0;63;26;21.0;15.0;69;29;29.4;85.0;51;1106;
2024/01/04;01:47:28;1704332848;16.0;59;23;18.0;14.0;69;29;29.4;84.8;53;1105;
2024/01/04;01:52:28;1704333148;17.0;61;24;20.0;15.0;73;32;29.2;84.5;54;1113;
2024/01/04;01:57:28;1704333448;18.0;63;26;19.0;15.0;71;31;28.8;83.8;54;1122;
2024/01/04;02:02:28;1704333748;17.0;61;24;18.0;14.0;72;31;28.5;83.3;55;1125;
2024/01/04;02:07:28;1704334048;16.0;59;23;18.0;13.0;1;1;28.1;82.6;56;1137;
2024/01/04;02:12:28;1704334348;15.0;57;21;17.0;11.0;70;30;27.8;82.0;55;1141;
2024/01/04;02:17:28;1704334648;15.0;57;21;17.0;13.0;74;33;27.4;81.4;54;1138;
2024/01/04;02:22:28;1704334948;15.0;57;21;17.0;12.0;74;33;27.1;80.8;53;1139;
2024/01/04;02:27:28;1704335248;15.0;57;21;17.0;12.0;75;34;26.7;80.1;53;1137;
2024/01/04;02:32:28;1704335548;15.0;57;21;16.0;11.0;76;34;26.4;79.6;53;1134;
2024/01/04;02:37:28;1704335848;16.0;59;23;19.0;13.0;78;36;26.2;79.1;54;1135;
2024/01/04;02:42:28;1704336148;15.0;57;21;17.0;12.0;78;36;26.0;78.7;56;1100;
2024/01/04;02:47:28;1704336448;16.0;59;23;19.0;12.0;82;39;25.9;78.5;58;1096;
2024/01/04;02:52:28;1704336748;17.0;61;24;20.0;13.0;80;37;25.8;78.4;59;1099;
2024/01/04;02:57:28;1704337048;14.0;55;20;16.0;11.0;83;39;25.7;78.2;60;1104;
2024/01/04;03:02:28;1704337348;15.0;57;21;17.0;12.0;86;41;25.6;78.1;62;1114;
2024/01/04;03:07:28;1704337648;15.0;57;21;17.0;12.0;1;1;25.6;78.1;64;1124;
2024/01/04;03:12:28;1704337948;17.0;61;24;19.0;13.0;87;42;25.6;78.2;65;1127;
2024/01/04;03:17:28;1704338248;15.0;57;21;17.0;12.0;87;42;25.5;78.0;64;1086;
2024/01/04;03:22:28;1704338548;14.0;55;20;17.0;11.0;84;40;25.7;78.2;64;1065;
2024/01/04;03:27:28;1704338848;15.0;57;21;16.0;12.0;88;43;25.9;78.6;63;1045;
2024/01/04;03:32:28;1704339148;17.0;61;24;18.0;15.0;90;44;26.1;78.9;63;1037;
2024/01/04;03:37:28;1704339448;15.0;57;21;17.0;13.0;91;44;26.2;79.2;63;1027;
2024/01/04;03:42:28;1704339748;14.0;55;20;16.0;11.0;90;44;26.4;79.5;62;1020;
2024/01/04;03:47:28;1704340048;18.0;63;26;21.0;15.0;93;46;26.5;79.8;62;1013;
2024/01/04;03:52:28;1704340348;17.0;61;24;18.0;15.0;90;44;26.7;80.0;62;1006;
2024/01/04;03:57:28;1704340648;15.0;57;21;16.0;13.0;92;45;26.8;80.2;60;997;
2024/01/04;04:02:28;1704340948;15.0;57;21;16.0;13.0;93;46;26.9;80.4;60;987;
2024/01/04;04:07:28;1704341248;15.0;57;21;17.0;13.0;1;1;27.0;80.6;60;980;
2024/01/04;04:12:28;1704341548;15.0;57;21;17.0;13.0;91;44;27.0;80.7;60;972;
2024/01/04;04:17:28;1704341848;15.0;57;21;16.0;13.0;88;43;27.1;80.8;60;966;
2024/01/04;04:22:28;1704342148;15.0;57;21;16.0;13.0;85;41;27.2;81.0;60;956;
2024/01/04;04:27:28;1704342448;16.0;59;23;17.0;14.0;83;39;27.3;81.1;60;950;
2024/01/04;04:32:28;1704342748;15.0;57;21;17.0;13.0;84;40;27.3;81.2;59;943;
2024/01/04;04:37:28;1704343048;16.0;59;23;18.0;14.0;81;38;27.4;81.3;59;941;
2024/01/04;04:42:28;1704343348;15.0;57;21;17.0;13.0;83;39;27.5;81.5;59;935;
2024/01/04;04:47:28;1704343648;15.0;57;21;16.0;13.0;84;40;27.5;81.6;59;929;
2024/01/04;04:52:28;1704343948;14.0;55;20;16.0;12.0;83;39;27.6;81.7;59;923;
2024/01/04;04:57:28;1704344248;16.0;59;23;17.0;14.0;82;39;27.7;81.8;59;915;
2024/01/04;05:02:28;1704344548;15.0;57;21;17.0;13.0;81;38;27.7;81.9;59;912;
2024/01/04;05:07:28;1704344848;16.0;59;23;18.0;14.0;1;1;27.7;81.9;59;903;
2024/01/04;05:12:28;1704345148;15.0;57;21;16.0;13.0;79;36;27.8;82.0;59;897;
2024/01/04;05:17:28;1704345448;15.0;57;21;16.0;13.0;78;36;27.8;82.0;59;894;
2024/01/04;05:22:28;1704345748;16.0;59;23;17.0;14.0;73;32;27.8;82.1;59;890;
2024/01/04;05:27:28;1704346048;15.0;57;21;16.0;13.0;71;31;27.9;82.2;58;884;
2024/01/04;05:32:28;1704346348;15.0;57;21;18.0;13.0;70;30;27.9;82.3;58;871;
2024/01/04;05:37:28;1704346648;15.0;57;21;16.0;13.0;69;29;28.0;82.3;58;870;
2024/01/04;05:42:28;1704346948;15.0;57;21;17.0;13.0;65;27;28.0;82.4;58;861;
2024/01/04;05:47:28;1704347248;14.0;55;20;17.0;12.0;65;27;28.0;82.4;58;860;
2024/01/04;05:52:28;1704347548;15.0;57;21;16.0;13.0;69;29;28.0;82.4;58;856;
2024/01/04;05:57:28;1704347848;15.0;57;21;17.0;13.0;65;27;28.1;82.5;58;850;
2024/01/04;06:02:28;1704348148;15.0;57;21;16.0;13.0;65;27;28.1;82.5;58;841;
2024/01/04;06:07:28;1704348448;14.0;55;20;15.0;12.0;1;1;28.1;82.6;58;836;
2024/01/04;06:12:28;1704348748;15.0;57;21;17.0;13.0;64;26;28.1;82.6;58;828;
2024/01/04;06:17:28;1704349048;17.0;61;24;20.0;15.0;66;28;28.2;82.7;58;813;
2024/01/04;06:22:28;1704349348;15.0;57;21;16.0;13.0;65;27;28.2;82.7;58;809;
2024/01/04;06:27:28;1704349648;15.0;57;21;17.0;13.0;65;27;28.2;82.8;58;803;
2024/01/04;06:32:28;1704349948;16.0;59;23;18.0;14.0;61;24;28.2;82.8;58;793;
2024/01/04;06:37:28;1704350248;15.0;57;21;18.0;13.0;68;29;28.3;82.9;58;790;
2024/01/04;06:42:28;1704350548;14.0;55;20;16.0;12.0;66;28;28.3;82.9;58;777;
2024/01/04;06:47:28;1704350848;15.0;57;21;17.0;13.0;66;28;28.3;82.9;58;777;
2024/01/04;06:52:28;1704351148;15.0;57;21;17.0;13.0;63;26;28.3;83.0;58;762;
2024/01/04;06:57:28;1704351448;14.0;55;20;15.0;12.0;65;27;28.3;83.0;58;750;
2024/01/04;07:02:28;1704351748;15.0;57;21;17.0;13.0;68;29;28.3;83.0;58;747;
2024/01/04;07:07:28;1704352048;14.0;55;20;16.0;12.0;1;1;28.3;83.0;58;738;
2024/01/04;07:12:28;1704352348;15.0;57;21;16.0;13.0;65;27;28.4;83.0;58;730;
2024/01/04;07:17:28;1704352648;14.0;55;20;16.0;12.0;77;35;28.4;83.1;58;721;
2024/01/04;07:22:28;1704352948;14.0;55;20;16.0;12.0;84;40;28.4;83.1;58;708;
2024/01/04;07:27:28;1704353248;14.0;55;20;16.0;12.0;73;32;28.4;83.2;58;708;
2024/01/04;07:32:28;1704353548;15.0;57;21;17.0;13.0;68;29;28.4;83.2;58;701;
2024/01/04;07:37:28;1704353848;16.0;59;23;18.0;14.0;69;29;28.5;83.2;58;690;
2024/01/04;07:42:28;1704354148;15.0;57;21;17.0;13.0;65;27;28.5;83.3;58;686;
2024/01/04;07:47:28;1704354448;15.0;57;21;16.0;13.0;71;31;28.5;83.3;58;683;
2024/01/04;07:52:28;1704354748;14.0;55;20;16.0;12.0;82;39;28.6;83.4;58;681;
2024/01/04;07:57:28;1704355048;15.0;57;21;16.0;13.0;155;86;28.6;83.4;58;669;
2024/01/04;08:02:28;1704355348;15.0;57;21;16.0;13.0;69;29;28.6;83.5;58;670;
2024/01/04;08:07:28;1704355648;14.0;55;20;16.0;12.0;1;1;28.6;83.5;58;659;
2024/01/04;08:12:28;1704355948;15.0;57;21;17.0;13.0;66;28;28.6;83.5;58;660;
2024/01/04;08:17:28;1704356248;15.0;57;21;19.0;13.0;70;30;28.7;83.6;58;654;
2024/01/04;08:22:28;1704356548;16.0;59;23;17.0;14.0;66;28;28.7;83.6;58;648;
2024/01/04;08:27:28;1704356848;15.0;57;21;17.0;13.0;69;29;28.7;83.7;57;643;
2024/01/04;08:32:28;1704357148;14.0;55;20;16.0;12.0;66;28;28.8;83.8;58;639;
2024/01/04;08:37:28;1704357448;15.0;57;21;17.0;13.0;65;27;28.8;83.8;58;639;
2024/01/04;08:42:28;1704357748;14.0;55;20;15.0;12.0;68;29;28.8;83.8;58;630;
2024/01/04;08:47:28;1704358048;14.0;55;20;15.0;12.0;64;26;28.8;83.9;57;626;
2024/01/04;08:52:28;1704358348;15.0;57;21;16.0;13.0;66;28;28.9;84.0;57;620;
2024/01/04;08:57:28;1704358648;15.0;57;21;17.0;13.0;68;29;28.9;84.0;58;609;
2024/01/04;09:02:28;1704358948;14.0;55;20;15.0;12.0;74;33;28.9;84.0;58;605;
2024/01/04;09:07:28;1704359248;15.0;57;21;17.0;13.0;1;1;28.9;84.1;58;599;
2024/01/04;09:12:28;1704359548;16.0;59;23;20.0;14.0;96;48;29.0;84.2;58;592;
2024/01/04;09:17:28;1704359848;15.0;57;21;16.0;13.0;111;56;29.1;84.3;58;586;
2024/01/04;09:22:28;1704360148;15.0;57;21;18.0;12.0;117;59;29.1;84.4;57;577;
2024/01/04;09:27:28;1704360448;15.0;57;21;18.0;13.0;98;49;29.1;84.5;57;573;
2024/01/04;09:32:28;1704360748;17.0;61;24;20.0;14.0;105;53;29.2;84.5;57;567;
2024/01/04;09:37:28;1704361048;17.0;61;24;21.0;14.0;84;40;29.2;84.6;57;558;
2024/01/04;09:42:28;1704361348;20.0;68;29;24.0;16.0;102;51;29.2;84.6;57;550;
2024/01/04;09:47:28;1704361648;17.0;61;24;20.0;14.0;86;41;29.3;84.7;57;551;
2024/01/04;09:52:28;1704361948;17.0;61;24;20.0;14.0;76;34;29.3;84.8;57;540;
2024/01/04;09:57:28;1704362248;16.0;59;23;19.0;14.0;72;31;29.4;84.9;57;536;
2024/01/04;10:02:28;1704362548;15.0;57;21;18.0;13.0;61;24;29.4;84.9;57;528;
2024/01/04;10:07:28;1704362848;16.0;59;23;19.0;14.0;1;1;29.5;85.1;57;520;
2024/01/04;10:12:28;1704363148;16.0;59;23;18.0;14.0;68;29;29.5;85.1;57;516;
2024/01/04;10:17:28;1704363448;16.0;59;23;20.0;14.0;77;35;29.6;85.2;57;503;
2024/01/04;10:22:28;1704363748;16.0;59;23;18.0;13.0;87;42;29.6;85.3;57;508;
2024/01/04;10:27:28;1704364048;16.0;59;23;18.0;14.0;68;29;29.6;85.3;57;497;
2024/01/04;10:32:28;1704364348;17.0;61;24;21.0;14.0;71;31;29.6;85.4;57;499;
2024/01/04;10:37:28;1704364648;17.0;61;24;19.0;15.0;66;28;29.7;85.5;57;496;
2024/01/04;10:42:28;1704364948;16.0;59;23;18.0;14.0;74;33;29.8;85.6;57;491;
2024/01/04;10:47:28;1704365248;17.0;61;24;23.0;14.0;87;42;29.8;85.7;57;491;
2024/01/04;10:52:28;1704365548;16.0;59;23;19.0;14.0;72;31;29.9;85.8;57;488;
2024/01/04;10:57:28;1704365848;19.0;66;27;23.0;17.0;68;29;29.9;85.9;57;480;
2024/01/04;11:02:28;1704366148;18.0;63;26;21.0;15.0;65;27;29.8;85.7;55;483;
2024/01/04;11:07:28;1704366448;18.0;63;26;20.0;16.0;1;1;29.4;84.9;55;503;
2024/01/04;11:12:28;1704366748;18.0;63;26;21.0;15.0;70;30;29.0;84.1;53;523;
2024/01/04;11:17:28;1704367048;15.0;57;21;17.0;13.0;87;42;28.5;83.3;50;544;
2024/01/04;11:22:28;1704367348;13.0;53;19;15.0;11.0;64;26;28.0;82.4;49;562;
2024/01/04;11:27:28;1704367648;17.0;61;24;18.0;14.0;65;27;27.6;81.6;48;578;
2024/01/04;11:32:28;1704367948;15.0;57;21;17.0;12.0;64;26;27.2;80.9;48;584;

Binary file not shown.

46
app.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#! /usr/bin/python3
from smb.SMBConnection import SMBConnection
from flask import Flask, jsonify, request
from threading import Thread
@ -7,19 +8,36 @@ import requests
import json
global last_indoor_data
global indoor_server_ip
global indoor_server_password
global outdoor_api_url
# Load the config file "config.json"
config = json.loads(open("config.json", "r").read())
indoor_server_ip = config["indoor_server_ip"]
indoor_server_password = config["indoor_server_password"]
outdoor_api_url = config["outdoor_api_url"]
# Assume that the indoor unit is offline
# The get_indoor_data() function will update this variable
last_indoor_data = {
"offline": True
}
def get_indoor_data() -> list:
global indoor_server_ip
global indoor_server_password
# SMB server details
server_name = "192.168.0.116"
server_name = indoor_server_ip
share_name = "airvisual"
username = "airvisual"
password = "6scprjag"
# File details
file_path = "202401_AirVisual_values.txt"
password = indoor_server_password
# File details, The file is a text file with name:
# <year><month>_AirVisual_values.txt
# Get the prefix of the file name
prefix = time.strftime("%Y%m", time.localtime())
file_path = prefix + "_AirVisual_values.txt"
# Connect to the SMB server
conn = SMBConnection(username, password, "", "")
@ -51,7 +69,7 @@ def get_indoor_data() -> list:
"PM10(ug/m3)": "pm10",
"PM1(ug/m3)": "pm1",
"CO2(ppm)": "co2",
"AQI(US)_indoor": "aqi",
"AQI(US)": "aqi",
"Temperature(C)": "temperature",
"Humidity(%RH)": "humidity",
"Timestamp": "time"
@ -110,13 +128,15 @@ def get_outdoor_data_current() -> dict:
}
open("outdoor_data_cache.txt", "w").write(json.dumps(default_data))
data = default_data
# Is the last_updated time more than 1 minute ago?
# Is the last_updated time more than 6 minute ago?
# If it is, fetch the data from the API
# If it is not, return the cached data
# Note that the cache file is a JSON object
data["last_updated"] = int(data["last_updated"])
if data["last_updated"] + 60 < int(time.time()):
url = "https://device.iqair.com/v2/64b63cdf45eeae29464b590d"
# Remove the last_updated key
if data["last_updated"] + 60*6 < int(time.time()):
global outdoor_api_url
url = outdoor_api_url
response = requests.get(url)
try:
print("Fetching data from API!" )
@ -143,15 +163,17 @@ def get_outdoor_data_current() -> dict:
data["last_updated"] = int(time.time())
open("outdoor_data_cache.txt", "w").write(json.dumps(data))
# Remove the last_updated key
del data["last_updated"]
return data
except:
# Oops, we got rate limited
# Return the cached data
print("Rate limited!")
# Remove the last_updated key
return data
else:
# Return the cached data
print("Using cached data!")
# Remove the last_updated key
return data
def merge_data(indoor_data_current: dict, outdoor_data: dict) -> dict:
@ -188,4 +210,6 @@ def get_data_route():
indoor_data = last_indoor_data
outdoor_data = get_outdoor_data_current()
merged_data = merge_data(indoor_data, outdoor_data)
return jsonify(merged_data)
return jsonify(merged_data)
app.run("0.0.0.0", 5000)

View File

@ -1 +1 @@
{"pm25": 23.5, "pm10": 37.5, "pm1": 18, "aqi": 75, "temperature": 29.4, "humidity": 51, "pressure": 101179, "time": "2024-01-03 23:18:32", "last_updated": 1704298803}
{"pm25": 21, "pm10": 35.5, "pm1": 14.5, "aqi": 70, "temperature": 29.1, "humidity": 55, "pressure": 101385, "time": "2024-01-04 11:03:32", "last_updated": 1704341266}

60
static/index.html Normal file
View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to the IQAir API Server</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
text-align: center;
}
h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
}
p {
font-size: 1.2rem;
margin-bottom: 2rem;
}
.button {
display: inline-block;
padding: 1rem 2rem;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 4px;
font-size: 1.2rem;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<h1>Welcome to the IQAir API Server</h1>
<p>Where are you?</p>
<a class="button" href="/satitm/index.html">SATITM</a>
<a class="button" href="/satite/index.html">SATITE</a>
</div>
</body>
</html>

225
static/index_global.html Normal file
View File

@ -0,0 +1,225 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Air Quality Dashboard</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script src="https://kit.fontawesome.com/34a5e0cdf4.js" crossorigin="anonymous"></script>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<script src="//code.iconify.design/1/1.0.6/iconify.min.js"></script>
<style>
body {
background-color: #828282;
font-family: "Roboto", sans-serif;
}
.card_frame {
margin-top: 10px;
margin-left: 10px;
display: grid;
width: 750px;
height: 230px;
border-radius: 30px;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
}
.top_element {
display: grid;
grid-template-columns: 1fr 2fr 2fr;
background-color: #97FF55;
border-top-right-radius: 30px;
border-top-left-radius: 30px;
height: 190px;
}
.bottom_element {
display: grid;
grid-template-columns: 1fr 1fr;
background-color: #ffffff;
border-bottom-right-radius: 30px;
border-bottom-left-radius: 30px;
height: 40px;
}
.indoor_aqi_block {
display: flex;
grid-template-columns: 1fr 1fr;
justify-content: center;
justify-items: center;
align-items: center;
background-color: #ffffff;
border-bottom-left-radius: 30px;
height: 40px;
border-right: 1px solid #828282;
}
.outdoor_aqi_block {
display: flex;
grid-template-columns: 1fr 1fr;
justify-content: center;
justify-items: center;
align-items: center;
background-color: #ffffff;
border-bottom-right-radius: 30px;
height: 40px;
border-left: 1px solid #828282;
}
.aqi_text {
font-size: 20px;
font-weight: 500;
color: #000000;
margin-left: 10px;
}
.health_icon_frame {
padding-top: 10px;
display: flex;
flex-direction: column;
justify-content: center;
justify-items: center;
align-items: center;
background-color: #7bdb3f;
border-top-left-radius: 30px;
font-size: 100px;
color: #fff;
}
.health_text {
font-size: 20px;
font-weight: 500;
color: #ffffff;
margin-left: 10px;
}
.pm25_frame {
display: flex;;
flex-direction: column;
justify-content: center;
justify-items: center;
align-items: center;
background-color: #ffffff;
border-radius: 30px;
font-size: 100px;
margin-bottom: 7px;
margin-left: 7px;
width: 270px;
color: #939393;
align-self: flex-end;
}
.pm25_text {
font-weight: 400;
color: #7a7a7a;
margin-left: 10px;
text-align: center;
font-size: 110px;
margin-top: 7px;
margin-bottom: 7px;
}
.pm25_location_text {
font-size: 20px;
font-weight: 400;
color: #000000;
margin-left: 10px;
margin-top: 7px;
margin-bottom: 7px;
}
.indoor_pm25_block .outdoor_pm25_block {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<div class="card_frame">
<div class="top_element" id="top_element">
<div class="health_icon_frame" id="health_icon_frame">
<span class="iconify" data-icon="mdi-heart" id="health_icon"></span>
<p class="health_text", id="health_text">Healthy</p>
</div>
<div class="indoor_pm25_block">
<p class="pm25_text", id="indoor-pm25">N/A</p>
<div class="pm25_frame">
<p class="pm25_location_text">Indoor PM2.5</p>
</div>
</div>
<div class="outdoor_pm25_block">
<p class="pm25_text", id="outdoor-pm25">N/A</p>
<div class="pm25_frame">
<p class="pm25_location_text">Outdoor PM2.5</p>
</div>
</div>
</div>
<div class="bottom_element">
<div class="indoor_aqi_block">
<i class="fa-solid fa-house"></i>
<p class="aqi_text" id="indoor-aqi">Indoor AQI: N/A</p>
</div>
<div class="outdoor_aqi_block">
<i class="fa-solid fa-tree"></i>
<p class="aqi_text" id="outdoor-aqi">Outdoor AQI: N/A</p>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
// Fetch data from API
function fetchData() {
var current_path = window.location.pathname;
// If current path end with index.html, remove it
if (current_path.endsWith("index.html")) {
current_path = current_path.replace("index.html", "");
}
$.get(current_path+"get_data", function(data) {
console.log(data);
// Update indoor AQI and PM2.5 values
$("#indoor-aqi").text("Indoor AQI: "+data.aqi_indoor);
$("#indoor-pm25").text(data.pm25_indoor);
// Update outdoor AQI and PM2.5 values
$("#outdoor-aqi").text("Outdoor AQI: "+data.aqi_outdoor);
$("#outdoor-pm25").text(data.pm25_outdoor);
// Is outdoor AQI healthy?
// If AQI is less than 50, it is healthy
// If AQI is between 50 and 100, it is unhealthy
// If AQI is more than 100, it is very unhealthy
var oldIcon = document.getElementById("health_icon");
oldIcon.parentNode.removeChild(oldIcon);
var newIcon = document.createElement("span");
newIcon.setAttribute("class", "iconify");
newIcon.setAttribute("data-inline", "false");
newIcon.id = "health_icon";
if (data.aqi_outdoor < 50) {
newIcon.setAttribute("data-icon", "mdi-heart");
Iconify.scanDOM();
$("#health_text").text("Healthy");
$("#top_element").css("background-color", "#97FF55");
$("#health_icon_frame").css("background-color", "#7bdb3f");
} else if (data.aqi_outdoor >= 50 && data.aqi_outdoor < 100) {
newIcon.setAttribute("data-icon", "mdi-smog");
Iconify.scanDOM();
$("#health_text").text("Moderate");
$("#top_element").css("background-color", "#FFD300");
$("#health_icon_frame").css("background-color", "#f9c300");
} else {
newIcon.setAttribute("data-icon", "mdi-skull-crossbones");
Iconify.scanDOM();
$("#health_text").text("Unhealthy");
$("#top_element").css("background-color", "#FF6969");
$("#health_icon_frame").css("background-color", "#A54444");
}
document.getElementById("health_icon_frame").appendChild(newIcon);
Iconify.scanDOM();
});
}
fetchData(); // Fetch data immediately when the page loads
setInterval(fetchData, 10000); // Fetch data every 10 seconds
});
</script>
</body>
</html>

1
static/satite/index.html Symbolic link
View File

@ -0,0 +1 @@
/app/iqair-apiserver/static/index_global.html

1
static/satitm/index.html Symbolic link
View File

@ -0,0 +1 @@
/app/iqair-apiserver/static/index_global.html

60
unit.json Normal file
View File

@ -0,0 +1,60 @@
{
"listeners": {
"*:80": {
"pass": "routes"
}
},
"routes": [
{
"match": {
"uri": [
"/satitm/get_data"
]
},
"action": {
"pass": "applications/iqair-apiserver-satitm",
"rewrite": "/get_data"
}
},
{
"match": {
"uri": [
"/satite/get_data"
]
},
"action": {
"pass": "applications/iqair-apiserver-satite",
"rewrite": "/get_data"
}
}, {
"match": {
"uri": [
"/*"
]
},
"action": {
"share": "/app/iqair-apiserver/static/$uri",
"index": "index.html"
}
}
],
"applications": {
"iqair-apiserver-satitm": {
"type": "python 3.10",
"path": "/app/iqair-apiserver",
"home": "/app/venv",
"module": "app",
"callable": "app",
"working_directory": "/app/env-satitm"
},
"iqair-apiserver-satite": {
"type": "python 3.10",
"path": "/app/iqair-apiserver",
"home": "/app/venv",
"module": "app",
"callable": "app",
"working_directory": "/app/env-satite"
}
}
}