使用Node.js,Raspberry Pi和LCD显示屏监控天气

在过去的几年中,销售的智能家居设备的数量一直稳定增长。预计到2021年将售出15亿台这些设备。每个智能家居中这些设备的平均数量为8.7。因此,您很有可能在家中至少有几个这样的设备。



在这方面,程序员比其他人具有一些优势,因为程序员可以独立地为智能家居创建设备。







我们拥有可供使用的可用组件,这些组件使我们能够快速构建各种设备。在这里,我想谈谈如何使用Raspberry Pi,LCD显示器和几行代码来组织天气监视。我们的系统将连接到Internet,因此它将使您可以监视地球上任何地方的天气。



先决条件



我想立即展示我所得到的。



图片


运行中的天气监控系统



由于这是一个DIY项目,因此在复制它之前,您需要掌握一些知识。即,我们正在谈论以下内容:



  • Raspberry Pi 3(或更高版本)。
  • 液晶显示器。
  • 连接电线。
  • 可变电阻器(可选)。
  • 面包板(可选)。


现在让我们谈谈如何将所有内容放在一起并进行设置。



步骤1.准备使用ClimaCell API并将显示器连接到板上



我们工作的第一步是获得访问ClimaCell API并将显示器连接到板上的密钥。



在这里,我们将使用ClimaCell Weather API作为天气数据的来源。通过此API,您可以访问各种指标,包括空气质量指标。



要使用ClimaCell API,您需要在项目网站上创建一个帐户,并获取一个API密钥,该密钥将用于对系统的请求进行签名。





ClimaCell API限制



系统中的注册是免费的,您每小时最多可以进行100个请求,每天可以执行的请求数限制为1000。这对于我们的项目来说已经绰绰有余。



一旦拥有了API密钥,我们就可以继续使用硬件组件,并开始将LCD显示器连接到Raspberry Pi。在将显示器连接到板上之前,请关闭其电源。



下图显示了Raspberry Pi 3上GPIO端口的布局。





Raspberry Pi 3 GPIO端口



图这是用于将显示器连接到板上的图。





显示屏到面板的连接图



通过此连接,显示屏将在全亮度和全对比度的情况下运行。亮度级别不是问题,但是对比度需要额外调整,否则您将无法在屏幕上辨认出任何东西。



这就是为什么我们需要至少一个可变电阻器,通过该电阻器我们可以调节显示器的对比度。





可变电阻器接线图



将显示器连接到板上后,我们可以打开Raspberry Pi。如果一切连接正确,显示屏将打开。借助可变电阻器,我们可以调整其对比度水平。



步骤2.准备Node.js项目



我们的项目的软件部分将基于Node.js的如果您的Raspberry Pi尚未安装此平台,请查看简单指南。



创建一个新文件夹并在其中运行命令npm init -y以初始化一个新的Node.js项目。然后运行命令npm install lcd node-fetch以安装我们需要的两个依赖项。



  • 该软件包lcd将用于组织液晶显示器的工作。
  • node-fetch我们需要该软件包以便向ClimaCell API发出HTTP请求。


上面说过,我们需要一个API密钥才能与ClimaCell API进行交互。该密钥可以放置在程序代码中,也可以放置在config.json用于存储项目设置的特殊文件中。



在使用的情况下,config.json我们正在谈论向其添加以下内容:



"cc_key": "<your_ClimaCell_API_key>"}


现在,完成Node.js项目的初步准备阶段,让我们将以下代码添加到其主文件中:



// * 
const Lcd = require("lcd");
const fs = require("fs");
const fetch = require("node-fetch");

// *  
const { cc_key } = JSON.parse(fs.readFileSync("./config.json"));


步骤3.使用LCD显示器



使用软件包lcd数据输出到LCD显示器是一项基本任务。程序包是底层显示引擎之上的抽象层。使用这种包可以使我们免于在显示器上显示数据时不得不解决许多小任务。



这是负责处理显示的代码。



const lcd = new Lcd({ rs: 26, e: 19, data: [13, 6, 5, 11], cols: 16, rows: 2 });

function writeToLcd(col, row, data) {
  return new Promise((resolve, reject) => {
    lcd.setCursor(col, row);
    lcd.print(data, (err) => {
      if (err) {
        reject();
      }
      resolve();
    });
  });
}


首先,我们lcd通过将带有参数的对象传递给适当的构造函数来创建对象,该构造函数除其他外还包含有关用于将显示器连接到板上的引脚的信息。



具有参数的对象的属性,colsrows指定显示的列数和行数。它使用16x2显示屏。例如,如果您使用另一台显示器,该显示器具有8列和1行,则分别用8和1替换数字16和2。



为了在显示器上显示某些内容,必须依次使用以下对象方法lcd



  • lcd.setCursor() -选择显示数据的位置。
  • lcd.print() -数据输出。


我们将对这些函数的调用放在了一个promise中,这样我们就可以使用async / await构造异步调用相应的操作。



现在,您应该已经可以在显示器上显示一些内容了。例如,执行命令writeToLcd(0,0,'Hello World')应导致从第一列开始在第一行显示text Hello World



步骤4.下载和显示天气信息



让我们开始下载天气信息并将其显示在显示屏上。



ClimaCell平台为我们提供了许多天气指示器,此外,还提供了有关空气质量的信息,有关空气中花粉水平的信息,有关交通风险的水平以及有关火灾的信息。我们有很多数据,但是我们不要忘记我们的显示只有16列和2行,即32个字符。



如果您需要在这样的显示器上显示大量数据,并且此限制似乎太强了,则可以使用滚动效果。



图片

滚动效果



这里,为了不使项目复杂化,我们限制自己在屏幕上显示以下数据:



  • 当前日期(时,分,秒)。
  • 温度。
  • 降水强度。


这是负责加载数据并显示数据的代码:



function getWeatherData(apiKey, lat, lon) {
  const url = `https://api.climacell.co/v3/weather/realtime?lat=${lat}&lon=${lon}&unit_system=si&fields=temp&fields=precipitation&apikey=${apiKey}`;

  const res = await fetch(url);
  const data = await res.json();
  return data;
}

async function printWeatherData() {
  const { temp, precipitation } = await getWeatherData(cc_key, 45.658, 25.6012);

  // *  
  await writeToLcd(0, 0, Math.round(temp.value) + temp.units);

  // *  
  const precipitationMessage =
    "Precip.: " + precipitation.value + precipitation.units;
  await writeToLcd(0, 1, precipitationMessage);


例如,要从ClimaCell获取某个城市的天气数据,您需要将地理坐标传递给API-纬度和经度。



要查找您所在城市的坐标,可以使用latlong.net之类的免费服务,然后将坐标config.json与API密钥一起保存在文件中这些数据很可能直接输入到代码中。



API返回的数据如下所示:



{
  lat: 45.658,
  lon: 25.6012,
  temp: { value: 17.56, units: 'C' },
  precipitation: { value: 0.3478, units: 'mm/hr' },
  observation_time: { value: '2020-06-22T16:30:22.941Z' }
}


使用解构分配机制,可以解析此对象,并在接收到有关温度和降水量的信息后,在显示屏的第一行和第二行中显示此信息。



步骤5.完成项目



我们只需要修改代码,并在收到新数据时更新屏幕上显示的信息。



async function main() {
  await printWeatherData();

  setInterval(() => {
    printWeatherData();
  }, 5 * 60 * 1000);

  setInterval(async () => {
    await writeToLcd(8, 0, new Date().toISOString().substring(11, 19));
  }, 1000);
}

lcd.on("ready", main);

// *     ctrl+c,     .
process.on("SIGINT", (_) => {
  lcd.close();
  process.exit();
});


天气数据每5分钟更新一次。但是,由于ClimaCell将对服务的请求数量限制为每分钟100个请求,因此我们可以走得更远,每分钟更新数据。



我们可以使用以下两种方法之一显示时间:



  • 您可以使用observation_time来自API对象的属性,并显示数据的到达时间。
  • 您可以制作一个真实的时钟并显示当前时间。


我选择了第二个选项,但您可能会选择其他方法。



要在显示屏的右上角显示时间,首先需要找到显示屏的开始位置。这将使数据整齐地适合可用的屏幕空间。要查找列号,请使用以下公式:



   -  ,   


时间信息的长度为8个字符,并且由于显示行的长度为16个字符,因此您需要在第8列开始显示此信息。



显示器的工作是异步组织的。因此,要知道何时初始化显示并准备就绪,我们必须使用library方法lcd.on()



与嵌入式系统一起使用的另一种推荐技术是在程序退出时释放资源。这就是为什么我们SIGINT在程序退出时使用事件处理程序释放显示资源的原因。



还有其他类似事件:



  • SIGUSR1SIGUSR2-用于拦截kill PID,例如重新启动nodemon
  • uncaughtException -捕获未处理的异常。


步骤6.连续脚本操作的组织



我们的脚本已经准备好,我们已经可以运行该程序了。但是,在确认项目完成之前,我们还有很多事情要做。



此时,您可能已使用SSH或直接连接到Raspberry Pi。但是,无论您如何连接至开发板,关闭端子时,程序都会停止。



同时,如果关闭板子,然后立即或稍后将其重新打开,脚本将不会自动启动。您将必须手动启动它。



为了解决这些问题,我们可以使用pm2之类的流程管理器



这是做什么的:



  • 安装pm2: sudo npm install pm2 -g
  • 为pm2创建启动脚本: sudo pm2 startup
  • 应用启动: pm2 start index.js
  • 保存服务器重启之间的进程列表: pm2 save


现在可以重新启动Raspberry Pi。该脚本将在设备准备就绪后运行。



结果



现在,您有了一个可随时监控天气的系统,您可以自定义所需的方式。如果知道天气数据对您来说非常重要(或者您想了解ClimaCell提供的其他指标,例如空气污染水平),则可以创建Raspberry Pi外壳,其中还可以安装LCD显示器。然后,在为该结构配备电池后,可以将其整齐地放置在某处。



Raspberry Pi是一个看起来很像普通计算机的主板。与使用Arduino等微控制器相比,使用它可以带来更多的乐趣因此,Raspberry Pi易于与您拥有的其他设备配对。



您是否打算做一些与本材料中讨论的内容类似的事情?






All Articles