This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <WiFiUdp.h> | |
#include "rtc_memory.hpp" | |
#include "config.h" | |
WiFiClient wifiClient; | |
struct { | |
char SSID[255] = WIFI_SSID; | |
char Password[255] = WIFI_PASS; | |
} wifi_config; | |
bool startWifi(int timeout) { | |
WiFi.disconnect(); | |
WiFi.mode(WIFI_STA); | |
Serial.println("Reading wifi_config"); | |
Serial.println("wifi_config:"); | |
Serial.print("SSID: "); | |
Serial.print(wifi_config.SSID); | |
Serial.print("\n"); | |
if (strlen(wifi_config.SSID) == 0) { | |
Serial.println("SSID is not configured"); | |
return false; | |
} | |
WiFi.begin(wifi_config.SSID, wifi_config.Password); | |
int time = 0; | |
for (;;) { | |
switch (WiFi.status()) { | |
case WL_CONNECTED: | |
Serial.println("connected!"); | |
WiFi.printDiag(Serial); | |
Serial.print("IPAddress: "); | |
Serial.println(WiFi.localIP()); | |
return true; | |
case WL_CONNECT_FAILED: | |
Serial.println("connect failed"); | |
return false; | |
} | |
delay(500); | |
Serial.print("."); | |
time++; | |
if (time >= timeout) { | |
break; | |
} | |
} | |
return false; | |
} | |
struct deep_sleep_data_t { | |
uint16_t count = 0; | |
uint8_t send = 0; | |
uint16_t data[12]; | |
void add_data(uint16_t n) { | |
data[count] = n; | |
} | |
template <class T> | |
void run_every_count(uint16_t n, T func) { | |
count++; | |
if (!send) { | |
send = count % (n - 1) == 0; | |
} else { | |
send = 0; | |
count = 0; | |
func(); | |
} | |
} | |
}; | |
rtc_memory<deep_sleep_data_t> deep_sleep_data; | |
void post_sensor_data(); | |
void setup() { | |
pinMode(13, OUTPUT); | |
Serial.begin(74880); | |
Serial.println("Initializing..."); | |
// データ読みこみ | |
if (!deep_sleep_data.read()) { | |
Serial.println("system_rtc_mem_read failed"); | |
} | |
Serial.print("deep_sleep_data->count = "); | |
Serial.println(deep_sleep_data->count); | |
// データの変更処理(任意) | |
deep_sleep_data->add_data(deep_sleep_data->count); | |
deep_sleep_data->run_every_count(4, [&]{ | |
Serial.println("send data"); | |
// なんか定期的に書きこみたい処理 | |
post_sensor_data(); | |
}); | |
if (!deep_sleep_data.write()) { | |
Serial.print("system_rtc_mem_write failed"); | |
} | |
if (deep_sleep_data->send) { | |
ESP.deepSleep(2.5e6, WAKE_RF_DEFAULT); | |
} else { | |
// sendしない場合は WIFI をオフで起動させる | |
ESP.deepSleep(2.5e6, WAKE_RF_DISABLED); | |
} | |
} | |
void loop() { | |
} | |
// dummy | |
void post_sensor_data() { | |
if (startWifi(30)) { | |
// do http etc... | |
WiFiUDP udp; | |
IPAddress serverIP(192, 168, 0, 5); | |
udp.beginPacket(serverIP, 5432); | |
udp.write((uint8_t*)deep_sleep_data->data, sizeof(deep_sleep_data->data)); | |
udp.endPacket(); | |
// wait for sending packet | |
delay(1000); | |
} else { | |
Serial.println("failed to start wifi"); | |
ESP.restart(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern "C" { | |
#include <user_interface.h> | |
}; | |
template <class T> | |
class rtc_memory { | |
// 4 bytes aligned memory block address in rtc memory. | |
// user data must use 64 or larger block. | |
// but system_rtc_mem_read() is failed for 64 so use 65. | |
static constexpr uint32_t USER_DATA_ADDR = 65; | |
static constexpr uint32_t USER_DATA_SIZE = 512 - ((USER_DATA_ADDR - 64) * 4); | |
static uint32_t fnv_1_hash_32(uint8_t *bytes, size_t length) { | |
static const uint32_t FNV_OFFSET_BASIS_32 = 2166136261U; | |
static const uint32_t FNV_PRIME_32 = 16777619U; | |
uint32_t hash = FNV_OFFSET_BASIS_32; | |
for (size_t i = 0 ; i < length ; ++i) hash = (FNV_PRIME_32 * hash) ^ (bytes[i]); | |
return hash; | |
} | |
uint32_t calc_hash(T& data) const { | |
return fnv_1_hash_32((uint8_t*)&data, sizeof(data)); | |
} | |
public: | |
uint32_t hash; | |
T data; | |
static_assert(sizeof(T) <= (USER_DATA_SIZE - sizeof(hash)), "sizeof(T) it too big"); | |
bool read() { | |
// Read memory to temporary variable to retain initial values in struct T. | |
rtc_memory<T> read; | |
// An initial rtc memory is random. | |
bool ok = system_rtc_mem_read(USER_DATA_ADDR, &read, sizeof(read)); | |
if (ok) { | |
// Only hashes are matched and copy to struct. | |
if (read.hash == calc_hash(read.data)) { | |
memcpy(this, &read, sizeof(read)); | |
} | |
} | |
return ok; | |
} | |
bool write() { | |
hash = calc_hash(data); | |
return system_rtc_mem_write(USER_DATA_ADDR, this, sizeof(*this)); | |
} | |
T* operator->() { | |
return &data; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment