次のシステムを構成するサブシステムです。
Grove IoT スターターキット for SORACOM で作るリモートカメラシステム
制作開始日
2021年8月16日
システムを構築している様子を報告していきます。
必要な技術については見通しが立っているので、それを組み合わせていきます。
完成日
2021年8月23日
画像のアップロードを MQTT から HTTP POST に変えて完成しました。
機能
HTTP GET でシャッター ON の信号を受け
画像を撮影
画像を HTTP で POST する。
要件
SD カードを使わない
フォルダー構造
$ tree remote_camera
remote_camera
├── camera_direct.ino
├── http_upload.ino
├── remote_camera.ino
└── setupLTE.ino
remote_camera.ino
// ---------------------------------------------------------------
/*
remote_camera.ino
Aug/22/2021 AM 08:30
Adafruit VC0706 TTL Serial Camera
*/
// ---------------------------------------------------------------
#include <WioLTEforArduino.h>
#include <Adafruit_VC0706.h>
#include <stdio.h>
#include <Base64.h>
#include <ArduinoJson.h>
#include <WioLTEClient.h>
#define cameraconnection Serial
#define URL "https://example.com/mqtt/http_to_mqtt/http_to_mqtt.py"
#define URL_STATUS "https://example.com/mqtt/mqtt_work/status.json"
// #define INTERVAL (9000)
#define INTERVAL (3000)
#define DATA_SIZE (512)
WioLTE Wio;
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
String device = "00000000";
WioLTEClient WioClient(&Wio);
int icount = 0;
// ---------------------------------------------------------------
// [4]:
void setup()
{
setupLTE();
Wio.PowerSupplyGrove(true);
Wio.LedSetRGB(0, 0, 1);
delay(500);
Wio.LedSetRGB(0, 1, 0);
delay(500);
snap_upload_proc();
SerialUSB.println("*** remote_camera.ino *** Aug/22/2021 AM 08:30 ***");
}
// ---------------------------------------------------------------
// [6]:
void loop()
{
delay(INTERVAL);
if (get_status_prc())
{
snap_upload_proc();
}
else
{
SerialUSB.println("*** status *** no ON ***");
}
icount++;
}
// ---------------------------------------------------------------
// [6-4]:
boolean get_status_prc()
{
boolean rvalue = true;
DynamicJsonDocument doc(512);
char data[512];
int dataSize;
dataSize=sizeof(data);
rvalue = Wio.HttpGet(URL_STATUS, data, dataSize);
if (!rvalue)
{
SerialUSB.println("### ERROR! HttpGet ###");
}
else
{
int llx = strlen(data);
SerialUSB.println("llx = " + String(llx));
data[llx] = '\0';
String msg = String(data);
SerialUSB.println(msg);
deserializeJson(doc, msg);
const char* button = doc["button"];
if (strstr(button,"on"))
{
rvalue = true;
SerialUSB.println("*** on ***");
}
else
{
rvalue = false;
SerialUSB.println("*** off ***");
SerialUSB.print("button = ");
SerialUSB.println(button);
}
}
SerialUSB.println("get_status_proc: rvalue = " + String(rvalue));
return rvalue;
}
// ---------------------------------------------------------------
// [4-4]:
void snap_upload_proc()
{
char str_json[8192];
camera_direct_proc(str_json);
http_upload_proc(str_json);
}
// ---------------------------------------------------------------
camera_direct.ino
// ---------------------------------------------------------------
/*
camera_dicrect.ino
Aug/23/2021 AM 08:00
*/
// ---------------------------------------------------------------
// [4]:
void camera_direct_proc(char str_json[])
{
char data_encoded[5000 + DATA_SIZE];
char data_jpg[5000 + DATA_SIZE];
SerialUSB.println("*** camera_direct_proc *** start ***");
Wio.LedSetRGB(1, 1, 0);
int length_jpg = image_retrieve_proc(data_jpg);
// SerialUSB.println("length_jpg = " + String(length_jpg));
int encodedLen = base64_enc_len(length_jpg);
// SerialUSB.println("encodedLen = " + String(encodedLen));
base64_encode(data_encoded,data_jpg,encodedLen);
Wio.LedSetRGB(1, 1, 1);
to_json_proc(data_encoded,str_json);
}
// ---------------------------------------------------------------
// [4-4]:
int image_retrieve_proc(char data_jpg[])
{
SerialUSB.println("*** image_retrieve_proc ***");
take_picture_proc();
// Get the size of the image (frame) taken
uint16_t jpglen = cam.frameLength();
SerialUSB.println("*** jpglen = " + String(jpglen));
int rvalue = jpglen;
SerialUSB.print("Storing ");
SerialUSB.print(jpglen, DEC);
SerialUSB.print(" byte image.");
int ipos = 0;
while (jpglen > 0) {
// read 64 bytes at a time;
uint8_t *buffer;
uint8_t bytesToRead = min((uint16_t)64, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
buffer = cam.readPicture(bytesToRead);
// strncpy(&data_jpg[ipos],(const char *)buffer,bytesToRead);
for (int it=0; it<bytesToRead; it++)
{
data_jpg[ipos+it] = buffer[it];
}
ipos += bytesToRead;
jpglen -= bytesToRead;
}
data_jpg[ipos] = '\0';
SerialUSB.println("*** ipos = " + String(ipos));
delay(500);
SerialUSB.println("*** image_retrieve_proc *** end ***");
return rvalue;
}
// ---------------------------------------------------------------
// [4-4-2]:
void take_picture_proc()
{
// Try to locate the camera
if (cam.begin()) {
SerialUSB.println("*** Camera Found. ***");
} else {
SerialUSB.println("No camera found?");
return;
}
// get_camera_version_proc();
// Set the picture size - you can choose one of 640x480, 320x240 or 160x120
// Remember that bigger pictures take longer to transmit!
// cam.setImageSize(VC0706_640x480); // biggest
// cam.setImageSize(VC0706_320x240); // medium
cam.setImageSize(VC0706_160x120); // small
Wio.PowerSupplyGrove(false);
delay(500);
Wio.PowerSupplyGrove(true);
// You can read the size back from the camera (optional, but maybe useful?)
uint8_t imgsize = cam.getImageSize();
SerialUSB.print("Image size: ");
if (imgsize == VC0706_640x480) SerialUSB.println("640x480");
if (imgsize == VC0706_320x240) SerialUSB.println("320x240");
if (imgsize == VC0706_160x120) SerialUSB.println("160x120");
delay(200);
if (! cam.takePicture())
SerialUSB.println("*** Failed to snap! ***");
else
SerialUSB.println("*** Picture taken! ***");
uint16_t jpglen = cam.frameLength();
SerialUSB.print("cam.frameLength: ");
SerialUSB.print(jpglen, DEC);
SerialUSB.println(" byte image.");
}
// ---------------------------------------------------------------
// [4-4-2-4]:
void get_camera_version_proc()
{
char *reply = cam.getVersion();
if (reply == 0)
{
SerialUSB.println("*** Failed to get version ***");
}
else
{
SerialUSB.println("-----------------");
SerialUSB.print(reply);
SerialUSB.println("-----------------");
}
}
// ---------------------------------------------------------------
void to_json_proc(char data_in[],char str_json_tt[])
{
char str_json[8192];
DynamicJsonDocument doc_camera(10512);
doc_camera["base64"] = String(data_in);
doc_camera["aa"] = "Hello";
doc_camera["version"] = "Aug/21/2021 PM 13:10";
doc_camera["device"] = device;
doc_camera["sizeofdata"] = strlen(data_in);
serializeJson(doc_camera, str_json);
SerialUSB.print(str_json);
delay(200);
SerialUSB.println("");
for (int it=0; it < 8192; it++)
{
str_json_tt[it] = str_json[it];
}
}
// ---------------------------------------------------------------
http_upload.ino
// ---------------------------------------------------------------
/*
http_upload.ino
Aug/20/2021 AM 08:00
*/
// ---------------------------------------------------------------
// [6-4]:
void http_upload_proc(char url_target[], char str_json[])
{
int status;
SerialUSB.println("*** http_upload_proc *** start ***");
if (!Wio.HttpPost(url_target, str_json, &status))
{
SerialUSB.println("### ERROR! HttpPost ###");
}
else
{
SerialUSB.print("Status: ");
SerialUSB.println(status);
}
delay(200);
SerialUSB.println("*** http_upload_proc *** end ***");
}
// ---------------------------------------------------------------
setupLTE.ino はこちら
UDP で温度と湿度を Harvest に送る