ESP32の稼働状態を外部から把握できるように、SNMPエージェントにします。
以下のライブラリを使わせていただきました。
0neblock/SNMP_Agent
ソース
こんな感じ
lib_snmp.cpp
#include <Arduino.h>
#include "main_config.h"
#ifdef _SNMP_AGENT_ENABLE_
#include <WiFi.h>
#include <WiFiUdp.h>
#include <SPIFFS.h>
#include <SNMP_Agent.h>
#include "wifi_utils.h"
#include "storage_info.h"
#include "quickjs_esp32.h"
#define IDEAL_LOOP_PERIOD 8000
static WiFiUDP udp;
static SNMPAgent snmp("public");
extern ESP32QuickJS qjs;
#define hrStorageOther ".1.3.6.1.2.1.25.2.1.1"
#define hrStorageRam ".1.3.6.1.2.1.25.2.1.2"
#define hrStorageVirtualMemory ".1.3.6.1.2.1.25.2.1.3"
#define hrStorageFixedDisk ".1.3.6.1.2.1.25.2.1.4"
#define hrStorageFlashMemory ".1.3.6.1.2.1.25.2.1.9"
static uint32_t lastLoopMicros = 0;
static int cpuLoadRaw = 0;
// 多重平均
static float avgFast = 0;
static float avgMid = 0;
static float avgSlow = 0;
long snmp_initialize(void)
{
if( !wifi_is_connected() )
return -1;
snmp.setUDP(&udp);
snmp.begin();
// system.sysDescr
snmp.addReadOnlyStaticStringHandler(
".1.3.6.1.2.1.1.1.0",
std::string("ESP32 SNMP Agent")
);
// system.sysObjectID
snmp.addOIDHandler(
".1.3.6.1.2.1.1.2.0",
".1.3.6.1.4.1.8072.3.2.255"
);
// system.sysUpTime
snmp.addDynamicReadOnlyTimestampHandler(
".1.3.6.1.2.1.1.3.0",
[]() -> uint32_t {
return millis() / 10;
}
);
// system.sysName
snmp.addReadOnlyStaticStringHandler(
".1.3.6.1.2.1.1.5.0",
std::string(MDNS_NAME)
);
// system.sysServices
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.1.7.0",
72
);
// interface.ifNumber
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.2.1.0",
1
);
// interface.ifIndex
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.2.2.1.1.1",
1
);
// interface.ifDescr
snmp.addReadOnlyStaticStringHandler(
".1.3.6.1.2.1.2.2.1.2.1",
std::string("wifi")
);
// interface.ifType
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.2.2.1.3.1",
71
);
// interface.ifMtu
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.2.2.1.4.1",
1500
);
uint8_t mac[6];
WiFi.macAddress(mac);
// interface.ifPhysAddress
snmp.addReadOnlyStaticStringHandler(
".1.3.6.1.2.1.2.2.1.6.1",
std::string((char*)mac, sizeof(mac))
);
// interface.ifAdminStatus
snmp.addReadOnlyIntegerHandler(
".1.3.6.1.2.1.2.2.1.7.1",
1
);
// interface.ifOperStatus
snmp.addDynamicIntegerHandler(
".1.3.6.1.2.1.2.2.1.8.1",
[]() -> int {
return (WiFi.status() == WL_CONNECTED) ? 1 : 2;
}
);
// 1:flash, 2:spiffs, 3:ram, 4:heap, 5:psram, 6:stack
// hrStorageType
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.1", hrStorageFlashMemory);
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.2", hrStorageFixedDisk);
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.3", hrStorageRam);
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.4", hrStorageRam);
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.5", hrStorageRam);
snmp.addOIDHandler(".1.3.6.1.2.1.25.2.3.1.2.6", hrStorageRam);
// hrStorageDescr
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.1", std::string("flash"));
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.2", std::string("spiffs"));
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.3", std::string("ram"));
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.4", std::string("heap"));
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.5", std::string("psram"));
snmp.addReadOnlyStaticStringHandler (".1.3.6.1.2.1.25.2.3.1.3.6", std::string("stack"));
// hrStorageAllocationUnits
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.1", 1);
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.2", 1);
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.3", 1);
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.4", 1);
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.5", 1);
snmp.addReadOnlyIntegerHandler (".1.3.6.1.2.1.25.2.3.1.4.6", 1);
// hrStorageSize
snmp.addReadOnlyIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.1", getFlashSize());
snmp.addReadOnlyIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.2", SPIFFS.totalBytes());
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.3",
[]() -> int {
return getRamTotal();
}
);
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.4",
[]() -> int {
return ESP.getHeapSize();
}
);
snmp.addReadOnlyIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.5", ESP.getPsramSize());
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.5.6",
[]() -> int {
JSMemoryUsage usage;
qjs.getMemoryUsage(&usage);
return usage.malloc_limit;
}
);
// hrStorageUsed
snmp.addReadOnlyIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.1", getPartitionApplication());
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.2",
[]() -> int {
return SPIFFS.usedBytes();
}
);
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.3",
[]() -> int {
return getRamUsed();
}
);
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.4",
[]() -> int {
return ESP.getFreeHeap();
}
);
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.5",
[]() -> int {
return ESP.getFreePsram();
}
);
snmp.addDynamicIntegerHandler(".1.3.6.1.2.1.25.2.3.1.6.6",
[]() -> int {
JSMemoryUsage usage;
qjs.getMemoryUsage(&usage);
return usage.malloc_size;
}
);
// hrProcessorLoad
snmp.addDynamicIntegerHandler(
".1.3.6.1.2.1.25.3.3.1.2.1",
[]() -> int {
return (int)(avgSlow + 0.5);
}
);
lastLoopMicros = micros();
return 0;
}
static void snmp_perform(void) {
uint32_t now = micros();
uint32_t diff = now - lastLoopMicros;
lastLoopMicros = now;
const uint32_t ideal = IDEAL_LOOP_PERIOD;
if (diff <= ideal) {
cpuLoadRaw = 0;
} else {
uint32_t over = diff - ideal;
cpuLoadRaw = over * 100 / ideal;
if (cpuLoadRaw > 100) cpuLoadRaw = 100;
}
avgFast = avgFast * 0.7 + cpuLoadRaw * 0.3;
avgMid = avgMid * 0.85 + avgFast * 0.15;
avgSlow = avgSlow * 0.95 + avgMid * 0.05;
}
long snmp_loop(void)
{
snmp_perform();
snmp.loop();
return 0;
}
#endif
ストレージ情報
storage_info.cpp
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_heap_caps.h"
unsigned long getRamUsed(void) {
multi_heap_info_t info;
heap_caps_get_info(&info, MALLOC_CAP_DEFAULT);
unsigned long used = info.total_allocated_bytes;
return used;
}
unsigned long getRamTotal(void) {
multi_heap_info_t info;
heap_caps_get_info(&info, MALLOC_CAP_DEFAULT);
unsigned long total = info.total_free_bytes + info.total_allocated_bytes;
return total;
}
unsigned long getPartitionApplication(void) {
const esp_partition_t* running = esp_ota_get_running_partition();
return running->size;
}
unsigned long getFlashSize(void) {
uint32_t flash_size = 0;
esp_flash_get_size(NULL, &flash_size);
return flash_size;
}
返している情報
| MIB | OID | 内容 |
|---|---|---|
| system.sysDescr | .1.3.6.1.2.1.1.1.0 | ”ESP32 SNMP Agent” |
| system.sysObjectID | .1.3.6.1.2.1.1.2.0 | unknown |
| system.sysUpTime | .1.3.6.1.2.1.1.3.0 | 起動してからの時間 |
| system.sysName | .1.3.6.1.2.1.1.5.0 | MDNS_NAME |
| system.sysServices | .1.3.6.1.2.1.1.7.0 | 72 |
| interface.ifNumber | .1.3.6.1.2.1.2.1.0 | 1 |
| interface.ifIndex | .1.3.6.1.2.1.2.2.1.1.1 | 1 |
| interface.ifDescr | .1.3.6.1.2.1.2.2.1.2.1 | "wifi" |
| interface.ifType | .1.3.6.1.2.1.2.2.1.3.1 | 71 |
| interface.ifMtu | .1.3.6.1.2.1.2.2.1.4.1 | 1500 |
| interface.ifPhysAddress | .1.3.6.1.2.1.2.2.1.6.1 | MAC アドレス |
| interface.ifAdminStatus | .1.3.6.1.2.1.2.2.1.7.1 | 1 |
| interface.ifOperStatus | .1.3.6.1.2.1.2.2.1.8.1 | WiFi 接続状態 |
| hrProcessorLoad | .1.3.6.1.2.1.25.3.3.1.2.1 | CPU 負荷 |
| hrStorageIndex | hrStorageType | hrStorageDescr | ストレージ種別 |
|---|---|---|---|
| 1 | hrStorageFlashMemory | "flash" | フラッシュ |
| 2 | hrStorageFixedDisk | "spiffs" | SPIFFS |
| 3 | hrStorageRam | "ram" | RAM |
| 4 | hrStorageRam | "heap" | ヒープ |
| 5 | hrStorageRam | "psram" | PSRAM |
| 6 | hrStorageRam | "stack" | スタック(Javascript) |
| MIB | OID(X=1~6) | 内容 |
|---|---|---|
| hrStorageType | .1.3.6.1.2.1.25.2.3.1.2.X | ストレージタイプ |
| hrStorageDescr | .1.3.6.1.2.1.25.2.3.1.3.X | ストレージ名 |
| hrStorageSize | .1.3.6.1.2.1.25.2.3.1.5.X | 全体ストレージサイズ |
| hrStorageUsed | .1.3.6.1.2.1.25.2.3.1.6.X | 使用済みストレージサイズ |
M5Stack Fire での実行例
$ snmpwalk -v1 192.168.1.XXX -c public
SNMPv2-MIB::sysDescr.0 = STRING: ESP32 SNMP Agent
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-TC::unknown
DISMAN-EXPRESSION-MIB::sysUpTimeInstance = Timeticks: (10582) 0:01:45.82
SNMPv2-MIB::sysName.0 = STRING: QuickJS_ESP32_M5Stack
SNMPv2-MIB::sysServices.0 = INTEGER: 72
IF-MIB::ifNumber.0 = INTEGER: 1
IF-MIB::ifIndex.1 = INTEGER: 1
IF-MIB::ifDescr.1 = STRING: wifi
IF-MIB::ifType.1 = INTEGER: ieee80211(71)
IF-MIB::ifMtu.1 = INTEGER: 1500
IF-MIB::ifPhysAddress.1 = STRING: XX:XX:XX:XX:XX:XX
IF-MIB::ifAdminStatus.1 = INTEGER: up(1)
IF-MIB::ifOperStatus.1 = INTEGER: up(1)
HOST-RESOURCES-MIB::hrStorageType.1 = OID: HOST-RESOURCES-TYPES::hrStorageFlashMemory
HOST-RESOURCES-MIB::hrStorageType.2 = OID: HOST-RESOURCES-TYPES::hrStorageFixedDisk
HOST-RESOURCES-MIB::hrStorageType.3 = OID: HOST-RESOURCES-TYPES::hrStorageRam
HOST-RESOURCES-MIB::hrStorageType.4 = OID: HOST-RESOURCES-TYPES::hrStorageRam
HOST-RESOURCES-MIB::hrStorageType.5 = OID: HOST-RESOURCES-TYPES::hrStorageRam
HOST-RESOURCES-MIB::hrStorageType.6 = OID: HOST-RESOURCES-TYPES::hrStorageRam
HOST-RESOURCES-MIB::hrStorageDescr.1 = STRING: flash
HOST-RESOURCES-MIB::hrStorageDescr.2 = STRING: spiffs
HOST-RESOURCES-MIB::hrStorageDescr.3 = STRING: ram
HOST-RESOURCES-MIB::hrStorageDescr.4 = STRING: heap
HOST-RESOURCES-MIB::hrStorageDescr.5 = STRING: psram
HOST-RESOURCES-MIB::hrStorageDescr.6 = STRING: stack
HOST-RESOURCES-MIB::hrStorageSize.1 = INTEGER: 16777216
HOST-RESOURCES-MIB::hrStorageSize.2 = INTEGER: 836081
HOST-RESOURCES-MIB::hrStorageSize.3 = INTEGER: 4445963
HOST-RESOURCES-MIB::hrStorageSize.4 = INTEGER: 281840
HOST-RESOURCES-MIB::hrStorageSize.5 = INTEGER: 4192123
HOST-RESOURCES-MIB::hrStorageSize.6 = INTEGER: 50352
HOST-RESOURCES-MIB::hrStorageUsed.1 = INTEGER: 3145728
HOST-RESOURCES-MIB::hrStorageUsed.2 = INTEGER: 4267
HOST-RESOURCES-MIB::hrStorageUsed.3 = INTEGER: 199004
HOST-RESOURCES-MIB::hrStorageUsed.4 = INTEGER: 66508
HOST-RESOURCES-MIB::hrStorageUsed.5 = INTEGER: 4187843
HOST-RESOURCES-MIB::hrStorageUsed.6 = INTEGER: 9456
HOST-RESOURCES-MIB::hrProcessorLoad.1 = INTEGER: 0
HOST-RESOURCES-MIB::hrProcessorLoad.1 = No more variables left in this MIB View (It is past the end of the MIB tree)
(参考) ESP32で動作するJavascript実行環境
ESP32で動作するJavascript実行環境を公開しています。
この中で実装しています。
「電子書籍:M5StackとJavascriptではじめるIoTデバイス制御」
サポートサイト
以上