ESP32-CAMで撮影した画像ををLINE notifyに転送する
ESP32で撮影した画像をLINEnotifyで確認できるようにしてみます。💪
1、システムの概要
接続のイメージはこんな感じです。
ESP32-CAMはHTTP serverとして動作させます。記載していませんが、ESP32-CAM、RaspberryPiはルーターを使ってwifiで接続しています。RaspberryPiはルータをゲートウェイとしてインターネットに接続していますので、外出先からESP32-CAMの撮影画像を見ることができます。
2、ESP32-CAMのプログラム
ちょっと長いですが、ほどんどはwifiとhttp serverとcameraの設定です。
ESP32をhttp server として立ち上げ、外部からhttpアクセスがあった場合、カメラで画像を撮影し、その画像をクライアントに送信しています。
クライアントに送信は画像ファイルじゃないとできないので、SDカードに画像ファイルを作成したあとでhttpで画像ファイルを送信するようにしています。
#include <esp_camera.h>
#include <FS.h>
#include <SD.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
const char* ssid = your ssid";
const char* password = "your pass";
WebServer server(80);
#define sd_sck 14
#define sd_mosi 15
#define sd_ss 13
#define sd_miso 2
// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
//****************************************************************
void handleNotFound() {
// ファイルが見つかりません
Serial.println("404 not found");
server.send(404, "text/plain", "File not found in Dongbeino...");
}
//------------------------------
void handleRoot(){
cameraShutterOn();
File file = SD.open("/test.jpg",FILE_READ);
server.streamFile(file,"image/jpeg");
file.close();
Serial.println("jpeg OK");
//server.send(200, "text/plain", "Hello ESP32");
}
//-------------------------------
void wifiSetUp(){
//wifiの設定
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp32cam")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
//****************************************************************
void cameraSetUp(){
static camera_config_t camera_config;
camera_config.ledc_channel = LEDC_CHANNEL_0;
camera_config.ledc_timer = LEDC_TIMER_0;
camera_config.pin_d0 = Y2_GPIO_NUM;
camera_config.pin_d1 = Y3_GPIO_NUM;
camera_config.pin_d2 = Y4_GPIO_NUM;
camera_config.pin_d3 = Y5_GPIO_NUM;
camera_config.pin_d4 = Y6_GPIO_NUM;
camera_config.pin_d5 = Y7_GPIO_NUM;
camera_config.pin_d6 = Y8_GPIO_NUM;
camera_config.pin_d7 = Y9_GPIO_NUM;
camera_config.pin_xclk = XCLK_GPIO_NUM;
camera_config.pin_pclk = PCLK_GPIO_NUM;
camera_config.pin_vsync = VSYNC_GPIO_NUM;
camera_config.pin_href = HREF_GPIO_NUM;
camera_config.pin_sscb_sda = SIOD_GPIO_NUM;
camera_config.pin_sscb_scl = SIOC_GPIO_NUM;
camera_config.pin_pwdn = PWDN_GPIO_NUM;
camera_config.pin_reset = RESET_GPIO_NUM;
camera_config.xclk_freq_hz = 20000000;
camera_config.pixel_format = PIXFORMAT_JPEG;
//init with high specs to pre-allocate larger buffers
if(psramFound()){
camera_config.frame_size = FRAMESIZE_UXGA;
camera_config.jpeg_quality = 10;
camera_config.fb_count = 2;
} else {
camera_config.frame_size = FRAMESIZE_SVGA;
camera_config.jpeg_quality = 12;
camera_config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
//initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_vflip(s, 1);//flip it back
s->set_brightness(s, 1);//up the blightness just a bit
s->set_saturation(s, -2);//lower the saturation
}
//drop down frame size for higher initial frame rate
s->set_framesize(s, FRAMESIZE_QVGA);
}
//-------------------------------------------------
void cameraShutterOn(){
/**/
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
if (fb->len <= 0) {
Serial.println("capture data size error");
return;
}
SD.begin(sd_ss);
File file = SD.open("/test.jpg",FILE_WRITE);
if (file.write(fb->buf, fb->len)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
esp_camera_fb_return(fb);
Serial.println("Finished.");
}
//****************************************************************
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
SPI.begin(sd_sck,sd_miso,sd_mosi,sd_ss);
cameraSetUp();
wifiSetUp();
}
void loop() {
server.handleClient();
}
3、RaspberryPiのプログラム
ESP32-CAMにhttp getのリクエストでアクセスしESP32-CAMが撮影した画像を取得します。
取得した画像はhttp postでLINE notifyに送ります。
LINE notifyの設定方法は下記を参考にして下さい!
import requests
import pprint
def main():
send_line_notify('Hello')
def send_line_notify(notification_message):
url = "http://esp32cam.local"
res = requests.get(url)
"""
LINEに通知する
"""
line_notify_token = 'your notify token'
line_notify_api = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': f'Bearer {line_notify_token}'}
#files = {'imageFile': open("test.jpg", "rb")}
files = {'imageFile': res.content}
data = {'message': notification_message}
response = requests.post(line_notify_api, headers = headers, data = data,files=files)
pprint.pprint(response.json())
if __name__ == "__main__":
main()
撮影タイミングはRaspberryPiがコンロトールします。今回はターミナルで実行していますが、センサ、時間、MQTTなど様々なものをトリガーにできると思います。💯
また、RaspberryPiを挟むことによって、ESP32-CAMを複数接続して、複数箇所からの画像を管理することもできますよ。
今回はESP32-CAMの撮影画像をSDカードにファイルにしてから、http送信してますが、なんとかSDカードなしでやりたいですね。
では🤚
この記事が気に入ったらサポートをしてみませんか?