DIY 迷你空氣站 #2 Code

搞完硬件之後係寫code
我打算將成個data變做一堆curve放上呢個server
所以先搞nextjs 先
慣例係先front end 後back end
javascript好處就係太多好用library
今次用既就係recharts

先睇example

    return (
      <ResponsiveContainer width="100%" height="100%">
        <LineChart
          width={500}
          height={300}
          data={data}
          margin={{
            top: 5,
            right: 30,
            left: 20,
            bottom: 5,
          }}
        >
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="name" />
          <YAxis />
          <Tooltip />
          <Legend />
          <Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{ r: 8 }} />
          <Line type="monotone" dataKey="uv" stroke="#82ca9d" />
        </LineChart>
      </ResponsiveContainer>
    );

data:

const data = [
  {
    name: 'Page A',
    uv: 4000,
    pv: 2400,
    amt: 2400,
  },
  {
    name: 'Page B',
    uv: 3000,
    pv: 1398,
    amt: 2210,
  },
  {
    name: 'Page C',
    uv: 2000,
    pv: 9800,
    amt: 2290,
  },
  {
    name: 'Page D',
    uv: 2780,
    pv: 3908,
    amt: 2000,
  },
  {
    name: 'Page E',
    uv: 1890,
    pv: 4800,
    amt: 2181,
  },
  {
    name: 'Page F',
    uv: 2390,
    pv: 3800,
    amt: 2500,
  },
  {
    name: 'Page G',
    uv: 3490,
    pv: 4300,
    amt: 2100,
  },
];

result: chart.png

有樣學樣 咁就照跟住整
唯一煩既係styling要用d心機去睇svg 既documentation
code.png

之後係nextjs backend
database 用左vercel既kv
其實即係redis黎
點解唔用sql係因為想試新野同埋但求就手
redis 入面有好多storage format
我用既係list 佢同array好接近 可以無限append落去
同埋用llibrary 去call既話
我可以好準確同快速咁拎到想要既data
例如係想要幾多點既溫度同拎幾多個sample都做到

而另外因為esp32 寫post method 既rest api 太麻煩
所以backend 係用search params 既型式去做
咁就用最普通既get method 都handle 到

最後幾行就KO左個backend啦

post data: backend.png

query data: code2.png

query data 因為係server side 既code 所以唔駛突登做個api endpoint俾佢
就咁wrap 做一個function就完事

之後就係ESP32
先用boilplate 連左屋企個Wifi同埋拎左sensor既data 先

void setup() {
  Serial.begin(9600);

  WiFi.mode(WIFI_STA);  
  WiFi.begin(ssid, pwd);

  Serial.print("WiFi connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.print("IP Address:");
  Serial.println(WiFi.localIP());
  Serial.print("WiFi RSSI:");
  Serial.println(WiFi.RSSI());  //

  mySerial.begin(9600);
  mySerial.listen();
  delay(5000);

  mySerial.write(0XA5);
  mySerial.write(0X55);
  mySerial.write(0X3F);
  mySerial.write(0X39);
  delay(100);

  mySerial.write(0XA5);
  mySerial.write(0X56);
  mySerial.write(0X02);
  mySerial.write(0XFD);
  Serial.println("Setup complete");

  delay(100);
}

然後每15分鐘經頭先寫完既api push一次data 上去

void loop() {
  float Temperature, Humidity;
  unsigned char i = 0, sum = 0;
  uint32_t Gas;
  uint32_t Pressure;
  uint16_t IAQ;
  int16_t Altitude;
  uint8_t IAQ_accuracy;
  //Serial.println("Checking serial...");
  while (mySerial.available()) {
    //Serial.println("mySerial available");
    Re_buf[counter] = (unsigned char)mySerial.read();

    if (counter == 0 && Re_buf[0] != 0x5A) {
      Serial.println("Nothing received");
    }
    if (counter == 1 && Re_buf[1] != 0x5A) {
      counter = 0;
      return;
    };
    counter++;
    if (counter == 20) {
      counter = 0;
      sign = 1;
    }
  }
  if (sign) {
    sign = 0;
    if (Re_buf[0] == 0x5A && Re_buf[1] == 0x5A) {
      for (i = 0; i < 19; i++)
        sum += Re_buf[i];
      if (sum == Re_buf[i]) {
        temp2 = (Re_buf[4] << 8 | Re_buf[5]);
        Temperature = (float)temp2 / 100;
        temp1 = (Re_buf[6] << 8 | Re_buf[7]);
        Humidity = (float)temp1 / 100;
        Pressure = ((uint32_t)Re_buf[8] << 16) | ((uint16_t)Re_buf[9] << 8) | Re_buf[10];
        float altPressure = (float(Pressure) + ALT_CORRECTION) / 100;
        IAQ_accuracy = (Re_buf[11] & 0xf0) >> 4;
        IAQ = ((Re_buf[11] & 0x0F) << 8) | Re_buf[12];
        Gas = ((uint32_t)Re_buf[13] << 24) | ((uint32_t)Re_buf[14] << 16) | ((uint16_t)Re_buf[15] << 8) | Re_buf[16];
        Altitude = (Re_buf[17] << 8) | Re_buf[18];


        if (millis() - prev > 60 * 15 * 1000) {

          String url = API_URL + "?temperature=" + String(Temperature) + "&humidity=" + String(Humidity);

          HTTPClient http;
          http.begin(url.c_str());

          // Send HTTP GET request
          int httpResponseCode = http.GET();

          if (httpResponseCode > 0) {
            Serial.print("HTTP Response code: ");
            Serial.println(httpResponseCode);
            //String payload = http.getString();
            //Serial.println(payload);
          } else {
            Serial.print("Error code: ");
            Serial.println(httpResponseCode);
          }
          // Free resources
          http.end();

          Serial.print("Temperature:");
          Serial.print(Temperature);
          Serial.print(" ,Humidity:");
          Serial.print(Humidity);
          Serial.print(" ,Pressure:");
          Serial.print(Pressure);
          Serial.print("|");
          Serial.print(altPressure);
          Serial.print("  ,IAQ:");
          Serial.print(IAQ);
          Serial.print(" ,Gas:");
          Serial.print(Gas);
          Serial.print("  ,Altitude:");
          Serial.print(Altitude);
          Serial.print("  ,IAQ_accuracy:");
          Serial.println(IAQ_accuracy);
          Serial.println("Submitted");

          prev = millis();
        }
      }
      delay(5000);
    }
  }

之後插電 試機
最後結果
result.png

而呢個IoT我都放左上呢個blog方便提下自己出門有冇記得熄冷氣咁樣
(多謝各位)

Copyright © tnlo.me. All rights reserved.