arduino(Blynk)のオブジェクトポインタの考え方について
Q&A
Closed
arduino(Blynk)のオブジェクトポインタの考え方について
やりたかったこと
BlynkでTimeinputのウィジェットを使ってStart,Stopの時間を入力して、
- 入力されたStart時間以降に何かしらの処理を定期的に実行
- 入力されたend時間以降に定期的に実行していた処理を停止
ということをさせたかったです。
つまずいた点
BlynkのTimeinputのウィジェットを使用するにはTimeInputParamを使うのですが、コンストラクタの指定が必須となっており、グローバル変数として定義できません。
下のコードのBLYNK_WRITE{}のparamをTimeInputParamのコンストラクタに渡す必要があります。
しかし、やりたいのは指定時間で処理の開始(定期実行)・指定時間で処理の停止を行いたいので、
BLYNK_WRITE{}の外(定期実行のBlink.timer 下記コードのvoid t())で指定時間で処理の開始・停止を記述する必要がありました。
やってみたこと
コンストラクタ必須のオブジェクトをポインタとして宣言し、
特定の条件下で実行される関数(下記コードでBLYNK_WRITE(V1) {})でオブジェクトを作成し、ポインタがその関数内で作られたオブジェクトを指すように記述した後、オブジェクトの破棄をせず
別の関数からポインタへアクセスしてオブジェクトを取得する方法で目的の動作はしました。
しかし、これはCのオブジェクトが明示的に開放するまで保持される仕様を悪用したものだと思われます。
試してはいませんが、スマホ上でTimeinputを何回も設定すると(BLYNK_WRITE(V1) {}が設定の度に実行される)メモリリークを起こしそうな気がします。
解決方法として思いつくのはTimeInputParamのプロパティ
- isWeekdaySelected(1)
- isWeekdaySelected(2)
- isWeekdaySelected(3)
- isWeekdaySelected(4)
- isWeekdaySelected(5)
- isWeekdaySelected(6)
- isWeekdaySelected(7)
- getStartHour
- getStartMinute
- getStopHour
- getStopMinute
をグローバル変数でboolやintを宣言しておき、BLYNK_WRITE(V1) {}実行時にそこに代入すればいいのだと思われます。
ただ個人的にはもっとスマートな書き方があるように思えます。
できるのかわかりませんが、例えば、オブジェクトをディープコピーする方法や、ポインタへの再定義時に以前のオブジェクトを開放する方法など。
質問
ポインタを更新する(コード上??許される??)記述はメモリリークを起こすのか?ということと、
もしもっとこうしたらいいという考え方があれば教えていただきたいと思います。
よろしくお願いいたします!!!
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#define JST 3600* 9
#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>
#include <Ticker.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "";
static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
TimeInputParam *StartStopTimeObj = NULL; // <---- ポインタ宣言
BlynkTimer timer; // Announcing the timer
WiFiUDP ntpUDP;
// You can specify the time server pool and the offset, (in seconds)
// additionaly you can specify the update interval (in milliseconds).
// NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
// NTPClient timeClient(ntpUDP, "192.168.1.1", JST, 60000);
NTPClient timeClient(ntpUDP, "ntp.nict.jp", JST, 60000);
BLYNK_CONNECTED(){
Blynk.syncAll();
}
BLYNK_WRITE(V1) {
// TimeInputParam t(param);
StartStopTimeObj = new TimeInputParam(param); // <---- ポインタがヒープ領域へ作られたオブジェクトを指すように指定 ??許される??
}
void setup() {
Serial.begin(115200);
delay(100);
Serial.print("\n\nStart\n");
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.println();
Serial.printf("Connected, IP address: ");
Serial.println(WiFi.localIP());
Blynk.begin(auth, ssid, pass, IPAddress(192, 168, 1, 26), 8080);
timer.setInterval(1000L, t); //timer will run every sec
}
void loop() {
timeClient.update();
Blynk.run();
timer.run();
}
void t()
{
char s[] = "{W} HH:MM:SS";
sprintf(s, "%s %02d:%02d:%02d", wd[timeClient.getDay()], timeClient.getHours(), timeClient.getMinutes(), timeClient.getSeconds());
Serial.println(s);
// Serial.println(timeClient.getFormattedTime());
// Process start time
char ss[] = "Input {Sun,Mon,Tue,Wed,Thr,Fri,Sat} HH:MM - HH:MM";
// Process weekdays (1. Mon, 2. Tue, 3. Wed, ...) // <---- ↓廃棄していないためたまたま残っている?ヒープ領域へ作られたオブジェクトへアクセス
sprintf(ss, "Input {%s,%s,%s,%s,%s,%s,%s} %02d:%02d -> %02d:%02d",
StartStopTimeObj->isWeekdaySelected(1) ? wd[1] : "---",
StartStopTimeObj->isWeekdaySelected(2) ? wd[2] : "---",
StartStopTimeObj->isWeekdaySelected(3) ? wd[3] : "---",
StartStopTimeObj->isWeekdaySelected(4) ? wd[4] : "---",
StartStopTimeObj->isWeekdaySelected(5) ? wd[5] : "---",
StartStopTimeObj->isWeekdaySelected(6) ? wd[6] : "---",
StartStopTimeObj->isWeekdaySelected(7) ? wd[0] : "---",
StartStopTimeObj->hasStartTime() ? StartStopTimeObj->getStartHour() : 99,
StartStopTimeObj->hasStartTime() ? StartStopTimeObj->getStartMinute() : 99,
StartStopTimeObj->hasStopTime() ? StartStopTimeObj->getStopHour() : 99,
StartStopTimeObj->hasStopTime() ? StartStopTimeObj->getStopMinute() : 99);
Serial.println(ss);
// <---- ↑廃棄していないためたまたま残っている?ヒープ領域へ作られたオブジェクトへアクセス
Serial.println();
delay(1000);
}