คำอธิบาย
รับข้อมูลจากอุปกรณ์เซนเซอร์และบันทึกลงฐานข้อมูล ระบบใช้ HMAC signature (MD5) เพื่อยืนยันตัวตน โดย signature = md5(apiKey + timestamp + uid)
Request Body (Content-Type: application/json)
| Field |
Type |
Required |
คำอธิบาย |
| uid |
string |
required |
UID ของเซนเซอร์ที่ลงทะเบียนในระบบ |
| timestamp |
number |
required |
Unix milliseconds (Date.now()) หรือ seconds (แปลงอัตโนมัติ) ต้องไม่เกิน 5 นาทีจากเวลาปัจจุบัน |
| signature |
string |
required |
MD5 hash ของ apiKey + timestamp + uid เพื่อยืนยันตัวตน |
| temperature |
number |
optional |
อุณหภูมิ (°C) |
| humidity |
number |
optional |
ความชื้นสัมพัทธ์ (%) |
| light |
number |
optional |
ความเข้มแสง (lux) |
| battery |
number |
optional |
แบตเตอรี่ (%) เช่น 87.5 |
Signature Formula: signature = md5(apiKey + timestamp + uid)
เช่น md5("sk_abc" + "1700000000000" + "S_xyz") = "d41d..."
ตัวอย่าง Request Body
{
"uid": "S_xxxxxxxxxxxxxxxx",
"timestamp": 1700000000000,
"signature": "d41d8cd98f00b204e9800998ecf8427e",
"temperature": 28.5,
"humidity": 65.2
}
Response Codes
200
OK — บันทึกข้อมูลสำเร็จ
{
"success": true,
"uid": "ABC123xyz",
"greenhouse": "gh-id-xxx",
"data": {
"uid": "ABC123xyz",
"sensorName": "เซนเซอร์ A",
"sensorType": "temperature",
"temperature": 28.5,
"humidity": 65.2,
"timestamp": 1700000000000
}
}
400
Bad Request — ไม่มี uid หรือเซนเซอร์ไม่ได้ผูกโรงเรือน
{"error": "Missing required field: uid"}
{"error": "Sensor is not linked to any greenhouse."}
401
Unauthorized — Signature ไม่ถูกต้อง
{"error": "Invalid signature."}
404
Not Found — ไม่พบ UID ในระบบ
{"error": "Sensor UID not found: ABC123xyz"}
405
Method Not Allowed — ใช้ได้เฉพาะ POST
{"error": "Method not allowed. Use POST."}
ตัวอย่างโค้ด
ESP8266 / Arduino
ESP32 (WiFiClient)
cURL
Python
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <MD5Builder.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* apiUrl = "https://<region>-<project>.cloudfunctions.net/sensorData";
const char* apiKey = "YOUR_FARM_API_KEY";
const char* sensorUid = "YOUR_SENSOR_UID";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); }
}
String md5Sign(String key, String ts, String uid) {
MD5Builder md5;
md5.begin();
md5.add(key + ts + uid);
md5.calculate();
return md5.toString();
}
void sendSensorData(float temp, float humid) {
if (WiFi.status() != WL_CONNECTED) return;
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
http.begin(client, apiUrl);
http.addHeader("Content-Type", "application/json");
String ts = String(millis());
String sig = md5Sign(apiKey, ts, sensorUid);
StaticJsonDocument<256> doc;
doc["uid"] = sensorUid;
doc["timestamp"] = ts;
doc["signature"] = sig;
doc["temperature"] = temp;
doc["humidity"] = humid;
String body;
serializeJson(doc, body);
int code = http.POST(body);
Serial.println(String("HTTP: ") + code);
http.end();
}
void loop() {
sendSensorData(28.5, 65.0);
delay(30000);
}
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include "mbedtls/md5.h"
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* apiUrl = "https://<region>-<project>.cloudfunctions.net/sensorData";
const char* apiKey = "YOUR_FARM_API_KEY";
const char* sensorUid = "YOUR_SENSOR_UID";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); }
}
String computeMD5(String input) {
unsigned char digest[16];
mbedtls_md5((const unsigned char*)input.c_str(), input.length(), digest);
String result = "";
for (int i = 0; i < 16; i++) {
char buf[3];
sprintf(buf, "%02x", digest[i]);
result += buf;
}
return result;
}
void sendData(float temp, float humid, float light) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
http.begin(client, apiUrl);
http.addHeader("Content-Type", "application/json");
String ts = String((long long)millis());
String sig = computeMD5(String(apiKey) + ts + String(sensorUid));
StaticJsonDocument<300> doc;
doc["uid"] = sensorUid;
doc["timestamp"] = ts;
doc["signature"] = sig;
doc["temperature"] = temp;
doc["humidity"] = humid;
doc["light"] = light;
String body;
serializeJson(doc, body);
int code = http.POST(body);
Serial.printf("HTTP %d\n", code);
http.end();
}
void loop() {
sendData(28.5, 65.0, 1200);
delay(30000);
}
TS=$(date +%s000)
SIG=$(echo -n "YOUR_FARM_API_KEY${TS}YOUR_SENSOR_UID" | md5sum | cut -d' ' -f1)
curl -X POST \
"https://<region>-<project>.cloudfunctions.net/sensorData" \
-H "Content-Type: application/json" \
-d "{
\"uid\": \"YOUR_SENSOR_UID\",
\"timestamp\": $TS,
\"signature\": \"$SIG\",
\"temperature\": 28.5,
\"humidity\": 65.0,
\"light\": 1200
}"
import hashlib, time, requests
url = "https://<region>-<project>.cloudfunctions.net/sensorData"
API_KEY = "YOUR_FARM_API_KEY"
SENSOR_UID = "YOUR_SENSOR_UID"
ts = str(int(time.time() * 1000))
sig = hashlib.md5((API_KEY + ts + SENSOR_UID).encode()).hexdigest()
payload = {
"uid": SENSOR_UID,
"timestamp": ts,
"signature": sig,
"temperature": 28.5,
"humidity": 65.0,
"light": 1200,
}
resp = requests.post(url, json=payload)
print(resp.status_code, resp.json())
การบันทึกข้อมูล
เมื่อส่งข้อมูลสำเร็จ ระบบจะบันทึกลง Firebase Realtime Database 2 ตำแหน่ง:
sensors/{greenhouseId}/current → { temperature, humidity, light, updatedAt }
sensors/{greenhouseId}/bySensor/{sensorUid} → { sensorName, sensorType, temperature, ... }
sensors/{greenhouseId}/history/{pushKey} → { uid, sensorName, temperature, ..., updatedAt }