153 lines
3.5 KiB
C++
153 lines
3.5 KiB
C++
/**
|
|
* @file
|
|
* @brief BACnet/IP application entry point for ESP32 PlatformIO environments
|
|
* @author Kato Gangstad
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
#include <cstring>
|
|
#if !defined(USE_M5STAMPLC_IO) || (USE_M5STAMPLC_IO)
|
|
#include <M5StamPLC.h>
|
|
#endif
|
|
#include <WiFi.h>
|
|
#if defined(USE_ETH_INTERFACE) && (USE_ETH_INTERFACE)
|
|
#include <ETH.h>
|
|
#endif
|
|
|
|
#ifndef PLC_INPUT_ACTIVE_LOW
|
|
#define PLC_INPUT_ACTIVE_LOW 0
|
|
#endif
|
|
|
|
#ifndef USE_M5STAMPLC_IO
|
|
#define USE_M5STAMPLC_IO 1
|
|
#endif
|
|
|
|
#ifndef USE_ETH_INTERFACE
|
|
#define USE_ETH_INTERFACE 0
|
|
#endif
|
|
|
|
#ifndef WIFI_SSID
|
|
#define WIFI_SSID ""
|
|
#endif
|
|
|
|
#ifndef WIFI_PASS
|
|
#define WIFI_PASS ""
|
|
#endif
|
|
|
|
#ifndef BACNET_IP_PORT
|
|
#define BACNET_IP_PORT 47808
|
|
#endif
|
|
|
|
extern "C" {
|
|
#include "bacnet_app.h"
|
|
}
|
|
|
|
/**
|
|
* @brief Bring up the selected WiFi or Ethernet interface
|
|
*/
|
|
static void wifi_connect(void)
|
|
{
|
|
#if USE_ETH_INTERFACE
|
|
Serial.println("[ETH] Starting Ethernet...");
|
|
if (!ETH.begin()) {
|
|
Serial.println("[ETH] ETH.begin() failed");
|
|
return;
|
|
}
|
|
|
|
unsigned long start = millis();
|
|
while (!ETH.linkUp() && ((millis() - start) < 15000UL)) {
|
|
delay(200);
|
|
Serial.print('.');
|
|
}
|
|
Serial.println();
|
|
|
|
if (ETH.linkUp()) {
|
|
Serial.printf(
|
|
"[ETH] Link up. IP: %s\n", ETH.localIP().toString().c_str());
|
|
} else {
|
|
Serial.println("[ETH] Link timeout");
|
|
}
|
|
#else
|
|
if (strlen(WIFI_SSID) == 0) {
|
|
Serial.println("[WIFI] SSID not configured; skipping WiFi connect");
|
|
return;
|
|
}
|
|
|
|
Serial.printf("[WIFI] Connecting to SSID: %s\n", WIFI_SSID);
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
|
|
|
unsigned long start = millis();
|
|
while ((WiFi.status() != WL_CONNECTED) && ((millis() - start) < 15000UL)) {
|
|
delay(200);
|
|
Serial.print('.');
|
|
}
|
|
|
|
Serial.println();
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
Serial.printf(
|
|
"[WIFI] Connected. IP: %s\n", WiFi.localIP().toString().c_str());
|
|
} else {
|
|
Serial.printf(
|
|
"[WIFI] Connect timeout. status=%d\n", (int)WiFi.status());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize the BACnet/IP application and selected board profile
|
|
*/
|
|
void setup(void)
|
|
{
|
|
Serial.begin(115200);
|
|
delay(100);
|
|
Serial.println("[BOOT] Mode: BACnet/IP");
|
|
Serial.printf("[BOOT] BACnet UDP Port: %u\n", (unsigned)BACNET_IP_PORT);
|
|
#if USE_ETH_INTERFACE
|
|
Serial.println("[BOOT] Network: Ethernet");
|
|
#else
|
|
Serial.println("[BOOT] Network: WiFi");
|
|
#endif
|
|
#if USE_M5STAMPLC_IO
|
|
Serial.println("[BOOT] Board profile: M5StamPLC I/O enabled");
|
|
M5StamPLC.begin();
|
|
#else
|
|
Serial.println("[BOOT] Board profile: Generic/ESP32-PoE (M5 I/O disabled)");
|
|
#endif
|
|
wifi_connect();
|
|
Serial.println("[BOOT] Init BACnet app...");
|
|
bacnet_app_init();
|
|
Serial.println("[BOOT] BACnet/IP ready");
|
|
}
|
|
|
|
/**
|
|
* @brief Run the main BACnet/IP application loop
|
|
*/
|
|
void loop(void)
|
|
{
|
|
#if USE_M5STAMPLC_IO
|
|
M5StamPLC.update();
|
|
|
|
for (uint8_t i = 0; i < bacnet_app_input_count(); i++) {
|
|
bool state = M5StamPLC.readPlcInput(i);
|
|
#if PLC_INPUT_ACTIVE_LOW
|
|
state = !state;
|
|
#endif
|
|
bacnet_app_input_set(i, state);
|
|
}
|
|
|
|
for (uint8_t i = 0; i < bacnet_app_relay_count(); i++) {
|
|
M5StamPLC.writePlcRelay(i, bacnet_app_relay_get(i));
|
|
}
|
|
|
|
bacnet_app_temperature_set(M5StamPLC.getTemp());
|
|
bacnet_app_free_heap_kb_set((float)ESP.getFreeHeap() / 1024.0f);
|
|
#else
|
|
bacnet_app_temperature_set(0.0f);
|
|
bacnet_app_free_heap_kb_set((float)ESP.getFreeHeap() / 1024.0f);
|
|
#endif
|
|
|
|
bacnet_app_tick();
|
|
delay(1);
|
|
}
|