建造一个气象站。最终帖子

2020-11-07 18:11:11

在本系列的最后一篇文章中,我们将介绍如何构建一个简单的气象站用户界面仪表板。

在上一篇文章中,我们构建了一个气象站机器人,它可以通知我们气象站的新测量结果。今天,我们将构建一个简单的rest API来从我们的服务器获取数据,并在一个简单的仪表板上绘制一个图表。

我们的Web界面将需要历史数据,这些数据将显示在图表中。在构建实际的用户界面之前,我们将创建一个rest API,它将返回存储在数据库中的所有传感器读数。API的代码位于weet_station_api.rs文件中。我们将使用Tower_web机箱来创建一个服务,该服务将返回所有传感器测量值及其时间戳。我们已经在上一篇文章中介绍了与数据库相关的代码。整个服务代码非常简洁:

/此类型将作为资源成为Web服务的一部分。#[Derate(Clone,Debug)]struct WeatherApi;/这将是JSON响应#[Derate(Response)]struct WeatherMessageResponse{Messages:vec<;WeatherMessage>;}impl_web!{impl WeatherApi{#[get(";/";)]#[Content_type(";json";)]FN GET_ALL_WeatherMessages(&。{让conn=establish_Connection(";./db.sqlite";);//这是一个最好保留在配置文件中的神奇字符串,但为了简单起见,我还是让它原样吧,让weweet_Messages=get_all_weet_Messages(&;conn);OK(WeatherMessageResponse{Messages:WeatherMessages})}}。

之后,我们所需要的就是在主函数内部的某个位置运行服务器:

让CORS=CorsBuilder::New().Allow_Origins(AllowOrigins::any{ALLOW_NULL:TRUE}).build();ServiceBuilder::New().resource(WeatherApi).中间件(CORS).run(&;addr).unwire();

您可以通过运行服务器并使用curl或Postman发出HTTP GET请求来检查API是否按预期工作。

现在,让我们创建一个简单的UI仪表板。我们界面的目的将是显示我们气象站的温度、湿度和气压读数的历史曲线图。我们不会使用任何复杂的Javascript框架,而是坚持使用普通的Javascript。最终结果如下所示:

<;html>;<;head<;<;link rel=";样式表";href=";style/weet_sit.css&34;/>;<;!--加载字体-->;<;link href=";https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&;display=swap";rel=";样式表&34;>;<;!--我们将使用的几个库-->;<;!--用于动画的css框架-->;<;link rel=";style heet=#34;href=";https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.min.css";/>;<;!--用于情节的chart.js-->;<;脚本src=";Https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js";>;<;/SCRIPT>;<;!--Moment.js用于处理日期-->;<;SCRIPT src=";https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js";>;<;/SCRIPT>;<;!--我们的主脚本,我们将在后面的😉--&>脚本src=";index.js";/脚本&>;<;/head&>;<;正文&><;!--让我们使用HTML5节标记将相关内容组合在一起,而不是使用模棱两可的div<;!--让我们研究一下这个脚本--&>;<;脚本src=";;/脚本&>;<;//head&>;<;主体&><;!--让我们使用HTML5节标记将相关内容组合在一起,而不是使用模棱两可的div&。Div class=";weatherIcon&34;>;<;Object Data=";img/weet_icon.svg";type=";Image/SVG+XML";>;/Object&>;<;/div&>;h1&>;span class=";accent&34;&&/Header>;<;段<;!--这是一组单选按钮--&>用户可以单击以在不同指标之间切换--<;<;div class=";group";&>;<;输入类型=";单选&34;名称=";rb";id=";temp_Radio";/>;输入类型=";单选";名称=";rb";id=";temp_Radio";/>;输入类型=";单选";名称=";rb#34;id=";>;温度<;/标签<;<;输入类型=";无线电";名称=";湿度无线电";/>;<;标签=";湿度<;/标签&><;输入类型=";无线电";名称=";无线电&##。/&>LABEL=";PRESSION_RADIO&34;>;PRESSION<;/LABEL&><;/div>;<;!--我们将在主脚本中传递给chart.js的画布--&><;div class=";chartContainer&34;>;<;canvas id=";tempChart。>;<;/canvas>;<;/div>;<;/section>;<;/body>;<;/html>;

完成标记后,我们现在可以通过在index.js脚本中实现一些逻辑来使仪表板变得有用。首先,让我们从最高抽象级别开始,从总体上看代码的作用:

Const API_Url=";http://localhost:8080";;//一旦加载完所有必要的资源,//页面//准备好呈现窗口,浏览器就会调用它。OnLoad=async()=>;{//从我们的API获取数据//我们只在必要的const data=await(aWait Fetch(API_URL))时使用异步调用来阻止执行。Json()//将时间戳转换为我们希望在图表中使用的标签格式Const Labels=Data。留言。地图(Items=>;Moment(It.。时间戳)。Format(';DDD HH a';));//呈现图表let chart=createChart(标签,数据);//创建可用于选择将显示在图表文档上的不同指标的单选按钮处理程序。GetElementById(";TEMP_RADIO";)。OnClick=()=>;{//此调用将准备要以chart.js期望的格式使用的数据。//输入Const tempData=createChartDataset(data,';temp&39;);//此函数将使用//新数据及其最小和最大界限updateChart(chart,tempData,tempData)更新已初始化的图表。Min-5,tempData。最大值+5);};文档。GetElementById(";PRESSION_RADIO";)。OnClick=()=>;{const pressureData=createChartDataset(data,';pressureData);updateChart(图表,pressureData,700,pressureData。最大+10);};文档。GetElementById(";湿度_无线";)。OnClick=()=>;{const humidityData=createChartDataset(data,';humidity';);updateChart(Chart,humidityData,0,100);};//将默认度量设置为温度文档。GetElementById(';TEMP_RADIO';)。单击();};

现在我们已经了解了整体情况,让我们来看看各个函数是如何工作的。我们将从createChart开始,它使用我们的画布显示使用chart.js库的绘图:

/*新建图表*@param{Arra.<;String>;}Labels*@param{Array}data*/函数createChart(Labels,Data){let CTX=Document。GetElementById(';tempChart';)。GetContext(';2d';);//设置颜色和字体图表。默认设置。全球性的。默认字体颜色=#636160ff;图表。默认设置。全球性的。DefaultFontFamily=';";Open Sans";,sans-serif;

/*使用数据更新给定图表并设置y轴的最小值和最大值*@param{ChartJS Object}Chart*@param{Object}data*@param{Number}min*@param{Number}max*/函数updateChart(Chart,Data,Min,Max){Chart。数据。数据集[0]。数据=数据。数据;图表。数据。数据集[0]。标签=数据。日期。地图(Items=>;Moment(It.。时间戳)。格式(';DDD HH a&39;));图表。选项。刻度。YAx[0]。扁虱。SuggestedMin=min;图表。选项。刻度。YAx[0]。扁虱。SuggestedMax=max;图表。更新();}。

这就是我们使用API获取和渲染气象站测量所需的一切。现在,让我们切换到造型部分,让它看起来更漂亮一些。

在这个项目中,我们将使用SASS扩展语言作为常规CSS的方便抽象。它允许以更干净、更易读的方式编写样式表。我不会详细介绍样式表,而是鼓励您克隆存储库,在浏览器中打开index.html文件,然后自己操作样式。页面样式和设计最好在实践中学习:安装sass、阅读文档和实验。

通过这篇文章,我们结束了从构建基于ESP32的气象站硬件、编写固件、编写跟踪所有测量的后端服务、构建电报通知机器人以及创建用于浏览历史数据的简单网络仪表板的旅程。我希望这篇文章能更好地揭示让硬件和软件解决特定问题的端到端过程。既然你已经涵盖了这个过程的每一个部分,下一步就是继续自己创造一些新的东西!😉