1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-02-24 20:53:07 +01:00

1 Commits

3 changed files with 210 additions and 17 deletions

View File

@@ -15,6 +15,7 @@
#include "images/logo64.xbm"
#include <esp32/clk.h>
#include "qrcode.h"
#include <vector>
#ifdef BOARD_OBP40S3
#include "dirent.h"
@@ -40,6 +41,7 @@ private:
String rtc_module;
String gps_module;
String env_module;
String flashLED;
String batt_sensor;
String solar_sensor;
@@ -50,6 +52,17 @@ private:
char mode = 'N'; // (N)ormal, (S)ettings, (D)evice list, (C)ard
#ifdef PATCH_N2K
struct device {
uint64_t NAME;
uint8_t id;
char hex_name[17];
uint16_t manuf_code;
const char *model;
};
std::vector<device> devicelist;
#endif
public:
PageSystem(CommonData &common){
commonData = &common;
@@ -76,6 +89,7 @@ public:
rot_sensor = common.config->getString(common.config->useRotSensor);
homelat = common.config->getString(common.config->homeLAT).toDouble();
homelon = common.config->getString(common.config->homeLON).toDouble();
flashLED = common.config->getString(common.config->flashLED);
}
void setupKeys() {
@@ -168,18 +182,42 @@ public:
}
}
int displayPage(PageData &pageData){
GwConfigHandler *config = commonData->config;
GwLog *logger = commonData->logger;
// Get config data
String flashLED = config->getString(config->flashLED);
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
void displayNew(PageData &pageData) {
#ifdef BOARD_OBP60S3
// Clear optical warning
if (flashLED == "Limit Violation") {
setBlinkingLED(false);
setFlashLED(false);
}
#endif
#ifdef PATCH_N2K
// load current device list
tN2kDeviceList *pDevList = pageData.api->getN2kDeviceList();
// TODO check if changed
if (pDevList->ReadResetIsListUpdated()) {
// only reload if changed
devicelist.clear();
for (uint8_t i = 0; i <= 252; i++) {
const tNMEA2000::tDevice *d = pDevList->FindDeviceBySource(i);
if (d == nullptr) {
continue;
}
device dev;
dev.id = i;
dev.NAME = d->GetName();
snprintf(dev.hex_name, sizeof(dev.hex_name), "%08X%08X", (uint32_t)(dev.NAME >> 32), (uint32_t)(dev.NAME & 0xFFFFFFFF));
dev.manuf_code = d->GetManufacturerCode();
dev.model = d->GetModelID();
devicelist.push_back(dev);
}
}
#endif
};
int displayPage(PageData &pageData){
GwConfigHandler *config = commonData->config;
GwLog *logger = commonData->logger;
// Logging boat values
logger->logDebug(GwLog::LOG, "Drawing at PageSystem, Mode=%c", mode);
@@ -461,12 +499,54 @@ public:
getdisplay().print("NMEA2000 device list");
getdisplay().setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(20, 80);
getdisplay().setCursor(20, 70);
getdisplay().print("RxD: ");
getdisplay().print(String(commonData->status.n2kRx));
getdisplay().setCursor(20, 100);
getdisplay().setCursor(120, 70);
getdisplay().print("TxD: ");
getdisplay().print(String(commonData->status.n2kTx));
#ifdef PATCH_N2K
x0 = 20;
y0 = 100;
getdisplay().setFont(&Ubuntu_Bold10pt8b);
getdisplay().setCursor(x0, y0);
getdisplay().print("ID");
getdisplay().setCursor(x0 + 50, y0);
getdisplay().print("Model");
getdisplay().setCursor(x0 + 250, y0);
getdisplay().print("Manuf.");
getdisplay().drawLine(18, y0 + 4, 360 , y0 + 4 , commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt8b);
y0 = 120;
uint8_t n_dev = 0;
for (const device& item : devicelist) {
if (n_dev > 8) {
break;
}
getdisplay().setCursor(x0, y0 + n_dev * 20);
getdisplay().print(item.id);
getdisplay().setCursor(x0 + 50, y0 + n_dev * 20);
getdisplay().print(item.model);
getdisplay().setCursor(x0 + 250, y0 + n_dev * 20);
getdisplay().print(item.manuf_code);
n_dev++;
}
getdisplay().setCursor(x0, y0 + (n_dev + 1) * 20);
if (n_dev == 0) {
getdisplay().printf("no devices found on bus");
} else {
getdisplay().drawLine(18, y0 + n_dev * 20, 360 , y0 + n_dev * 20, commonData->fgcolor);
getdisplay().printf("%d devices of %d in total", n_dev, devicelist.size());
}
#else
getdisplay().setCursor(20, 100);
getdisplay().print("NMEA2000 not exposed to obp60 task");
#endif
}
// Update display

View File

@@ -2,6 +2,14 @@
import subprocess
def cleanup_patches(source, target, env):
for p in patchfiles:
patch = os.path.join(patchdir, p)
print(f"removing {patch}")
res = subprocess.run(["git", "apply", "-R", patch], capture_output=True, text=True)
if res.returncode != 0:
print(res.stderr)
patching = False
epdtype = "unknown"
@@ -46,11 +54,13 @@ if patching:
print("patchdir not found, no patches applied")
else:
patchfiles = [f for f in os.listdir(patchdir)]
for p in patchfiles:
patch = os.path.join(patchdir, p)
print(f"applying {patch}")
res = subprocess.run(["git", "apply", patch], capture_output=True, text=True)
if res.returncode != 0:
print(res.stderr)
if len(patchfiles) > 0:
for p in patchfiles:
patch = os.path.join(patchdir, p)
print(f"applying {patch}")
res = subprocess.run(["git", "apply", patch], capture_output=True, text=True)
if res.returncode != 0:
print(res.stderr)
env.AddPostAction("$PROGPATH", cleanup_patches)
else:
print("no patches found")

View File

@@ -0,0 +1,103 @@
diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h
index 88f9690..9663a65 100644
--- a/lib/api/GwApi.h
+++ b/lib/api/GwApi.h
@@ -2,6 +2,8 @@
#define _GWAPI_H
#include "GwMessage.h"
#include "N2kMsg.h"
+#include "Nmea2kTwai.h"
+#include "N2kDeviceList.h"
#include "NMEA0183Msg.h"
#include "GWConfig.h"
#include "GwBoatData.h"
@@ -222,6 +224,8 @@ class GwApi{
* accessing boat data must only be executed from within the main thread
* you need to use the request pattern as shown in GwExampleTask.cpp
*/
+ virtual Nmea2kTwai *getNMEA2000()=0;
+ virtual tN2kDeviceList *getN2kDeviceList()=0;
virtual GwBoatData *getBoatData()=0;
virtual ~GwApi(){}
};
diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h
index 604c356..2fe4496 100644
--- a/lib/obp60task/OBP60Extensions.h
+++ b/lib/obp60task/OBP60Extensions.h
@@ -15,6 +15,9 @@
#define MOUNT_POINT "/sdcard"
#endif
+// Patches to apply to gateway code
+#define PATCH_N2K
+
// FRAM address reservations 32kB: 0x0000 - 0x7FFF
// 0x0000 - 0x03ff: single variables
#define FRAM_PAGE_NO 0x0002
diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp
index 1b007f8..90087d4 100644
--- a/lib/usercode/GwUserCode.cpp
+++ b/lib/usercode/GwUserCode.cpp
@@ -216,6 +216,14 @@ public:
{
return api->getLogger();
}
+ virtual Nmea2kTwai *getNMEA2000()
+ {
+ return api->getNMEA2000();
+ }
+ virtual tN2kDeviceList *getN2kDeviceList()
+ {
+ return api->getN2kDeviceList();
+ }
virtual GwBoatData *getBoatData()
{
return api->getBoatData();
@@ -428,4 +436,4 @@ void GwUserCode::handleWebRequest(const String &url,AsyncWebServerRequest *req){
}
LOG_DEBUG(GwLog::DEBUG,"no task found for web request %s[%s]",url.c_str(),tname.c_str());
req->send(404, "text/plain", "not found");
-}
\ No newline at end of file
+}
diff --git a/src/main.cpp b/src/main.cpp
index 44c715f..fdb0366 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -100,6 +100,7 @@ GwLog logger(LOGLEVEL,NULL);
GwConfigHandler config(&logger);
#include "Nmea2kTwai.h"
+#include <N2kDeviceList.h>
static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms
static const unsigned long NMEA2000_HEARTBEAT_INTERVAL=5000;
class Nmea2kTwaiLog : public Nmea2kTwai{
@@ -126,6 +127,7 @@ class Nmea2kTwaiLog : public Nmea2kTwai{
#endif
Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog((gpio_num_t)ESP32_CAN_TX_PIN,(gpio_num_t)ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger));
+tN2kDeviceList *pN2kDeviceList;
#ifdef GWBUTTON_PIN
bool fixedApPass=false;
@@ -333,6 +335,12 @@ public:
status.n2kTx=countNMEA2KOut.getGlobal();
channels.fillStatus(status);
}
+ virtual Nmea2kTwai *getNMEA2000(){
+ return &NMEA2000;
+ }
+ virtual tN2kDeviceList *getN2kDeviceList(){
+ return pN2kDeviceList;
+ }
virtual GwBoatData *getBoatData(){
return &boatData;
}
@@ -935,6 +943,7 @@ void setup() {
NMEA2000.SetMsgHandler([](const tN2kMsg &n2kMsg){
handleN2kMessage(n2kMsg,N2K_CHANNEL_ID);
});
+ pN2kDeviceList = new tN2kDeviceList(&NMEA2000);
NMEA2000.Open();
logger.logDebug(GwLog::LOG,"starting addon tasks");
logger.flush();