22 Commits

Author SHA1 Message Date
268c204957 added LoraUartCommand Interpreter 2023-05-25 19:59:34 +02:00
65d51f13aa added Pinout for LoRa-UART 2023-05-25 14:00:18 +02:00
f727bb3247 first Draft of UART for external LoRa-Module 2023-05-25 14:00:06 +02:00
cd1379f90c updated project-config 2023-05-25 10:58:50 +02:00
0363b1eebc increase Version after Release 2023-04-30 10:08:34 +02:00
e6f1283aae final fixes before Release for DE XI 2023-04-30 10:05:41 +02:00
a92b1edfd9 reformated points-table on WebUI 2023-04-18 20:07:52 +02:00
4cce7c1c86 fixed show setting in WebUI 2023-04-18 20:07:38 +02:00
0a1625e9b8 made Faction-Names configurable 2023-04-18 20:06:57 +02:00
c24829ed70 added Device-ID to SystemInfo 2023-04-18 13:00:34 +02:00
a102405596 reverted calculation-order of checksum and store 2023-04-18 12:53:27 +02:00
1b7157dbdc read back EEPROM after Format to Maintain DTC 2023-04-18 12:50:26 +02:00
cad34d6b84 swapped migration of Persistance and Config 2023-04-18 12:47:04 +02:00
701bf9f457 fixed another warning and bug in Logoutput 2023-04-18 12:30:14 +02:00
0a895a00b9 fixed warning 2023-04-18 12:29:55 +02:00
22a62e3d1e refactoring 2023-04-18 12:28:11 +02:00
f48b5a09ed renamed eeprom-files and added migrator 2023-04-18 12:27:04 +02:00
7f6c486eab fixed config if checkbox not set 2023-04-17 23:14:46 +02:00
3e77f89538 propely handle sysstart and display Startup 2023-04-17 23:12:13 +02:00
f33076a0a3 fixed typo 2023-04-17 22:57:43 +02:00
7e58db489d made active faction recovery configurable 2023-04-17 22:55:16 +02:00
eb771d07d3 fixed copy&paste-error 2023-04-17 22:29:19 +02:00
21 changed files with 531 additions and 131 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -77,31 +77,28 @@
<hr />
<p>
<h4>aktueller Punktestand</h4>
<div class="table-responsive">
<table class="table table-borderless table-dark">
<thead>
<tr>
<th class="text-center" scope="col">%NAME_FAC_1%</th>
<th class="text-center" scope="col">%NAME_FAC_2%</th>
<th class="text-center" scope="col">%NAME_FAC_3%</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mx-auto"><img src="static/img/logo_fac1.png" class="rounded mx-auto img-fluid d-block"
alt="..."></td>
<td class="mx-auto"><img src="static/img/logo_fac2.png" class="rounded mx-auto img-fluid d-block"
alt="..."></td>
<td class="mx-auto"><img src="static/img/logo_fac3.png" class="rounded mx-auto img-fluid d-block"
alt="..."></td>
</tr>
<tr>
<td class="text-center">%POINTS_FAC_1%</td>
<td class="text-center">%POINTS_FAC_2%</td>
<td class="text-center">%POINTS_FAC_3%</td>
</tr>
</tbody>
</table>
<div class="container-fluid">
<div class="row">
<div class="col text-center %FACTION_1_ACTIVE% text-white p-3">%NAME_FAC_1%</div>
<div class="col text-center %FACTION_2_ACTIVE% text-white p-3">%NAME_FAC_2%</div>
<div class="col text-center %FACTION_3_ACTIVE% text-white p-3">%NAME_FAC_3%</div>
</div>
<div class="row">
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac1.png"
class="rounded mx-auto img-fluid d-block" alt="...">
</div>
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac2.png"
class="rounded mx-auto img-fluid d-block" alt="...">
</div>
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac3.png"
class="rounded mx-auto img-fluid d-block" alt="...">
</div>
</div>
<div class="row">
<div class="col text-center bg-secondary text-white p-3">%POINTS_FAC_1%</div>
<div class="col text-center bg-secondary text-white p-3">%POINTS_FAC_2%</div>
<div class="col text-center bg-secondary text-white p-3">%POINTS_FAC_3%</div>
</div>
</div>
</p>
<!-- Div GroupFaction Points -->
@@ -204,8 +201,8 @@
<!-- Div Group Battery Type -->
<hr />
<p>
<h4>Akku-Variante</h4>
<form action="post.htm" method="POST" class="form-horizontal">
<h4>Akku-Variante</h4>
<div class="form-group row">
<label for="battery_select" class="control-label col-4">Akku</label>
<div class="col-8">
@@ -214,6 +211,60 @@
</select>
</div>
</div>
<h4>Timer-Einstellungen</h4>
<div class="form-group row">
<label for="factionreboot_cont" class="control-label col-4">active Faction Recovery</label>
<div class="col-8">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="factionreboot_cont" id="factionreboot_cont"
%FACTIONREBOOT_CHECKED%>
<label class="form-check-label" for="factionreboot_cont">
aktive Faktion beim booten wiederherstellen ?
</label>
</div>
</div>
</div>
<h4>Faktionsbezeichnungen</h4>
<div class="alert alert-primary alert-dismissable show fade" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>Achtung!</strong><br>
Faktionsbezeichnungen können nur aus ASCII-Zeichen bestehen, also A-Z, a-z und 0-9
</div>
<div class="form-group row">
<label for="faction_1_name" class="control-label col-4">Faktion 1</label>
<div class="col-8">
<div class="input-group">
<input id="faction_1_name" name="faction_1_name" value="%NAME_FAC_1%" type="text" class="form-control" pattern="[A-Za-z0-9 _-]{1,32}">
<div class="input-group-append">
<span class="input-group-text">max 32 Zeichen</span>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="faction_2_name" class="control-label col-4">Faktion 2</label>
<div class="col-8">
<div class="input-group">
<input id="faction_2_name" name="faction_2_name" value="%NAME_FAC_2%" type="text" class="form-control" pattern="[A-Za-z0-9 _-]{1,32}">
<div class="input-group-append">
<span class="input-group-text">max 32 Zeichen</span>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="faction_3_name" class="control-label col-4">Faktion 3</label>
<div class="col-8">
<div class="input-group">
<input id="faction_3_name" name="faction_3_name" value="%NAME_FAC_3%" type="text" class="form-control" pattern="[A-Za-z0-9 _-]{1,32}">
<div class="input-group-append">
<span class="input-group-text">max 32 Zeichen</span>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col text-center">
<button name="settingssave" type="submit" class="btn btn-outline-primary">&Uuml;bernehmen</button>
@@ -242,6 +293,10 @@
<td>Hostname</td>
<td>%HOSTNAME%</td>
</tr>
<tr>
<td>Device-ID</td>
<td>%DEVICENAME_ID%</td>
</tr>
<tr>
<td>Battery Voltage</td>
<td>%BAT_VOLTAGE%V</td>
@@ -267,6 +322,10 @@
<td>Battery_type</td>
<td>%BATTERY_TYPE%</td>
</tr>
<tr>
<td>Faction_recovery</td>
<td>%FACTION_RECOVERY%</td>
</tr>
<tr>
<td>EEPROM Version</td>
<td>%EEPROM_VERSION%</td>
@@ -430,7 +489,7 @@
<div class="container-fluid text-center">
<div class="footer-copyright text-center py-3">
<span class="text-muted">© 2023 -
<a class="text-reset fw-bold" href="https://hiabuto.de/">Hiabuto Defence Systems</a></span>
<a class="text-reset fw-bold" href="https://hiabuto.de/">Hiabuto Defense Systems</a></span>
</div>
</div>
</footer>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,4 @@
{
"title": "EEPROM-Migration failed",
"description": "Migration of EEPROM-Image from an other FW-Version failed - you need to reset everything manually!"
}

View File

@@ -1 +1 @@
1.02
1.03

View File

@@ -19,6 +19,7 @@ typedef enum DTCNums_e
DTC_NO_BATMNON_FOUND,
DTC_BAT_LOW,
DTC_BAT_CRITICAL,
DTC_EEPROM_MIGRATE_FAILED,
DTC_LAST_DTC
} DTCNums_t;

View File

@@ -1,5 +1,5 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <Arduino.h>
#include <Wire.h>
@@ -8,7 +8,9 @@
#include "globals.h"
#include "dtc.h"
#include "common.h"
#include "debugger.h"
#define I2C_EE_ADDRESS 0x50
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC64
#define EEPROM_ENDURANCE 1000000
@@ -30,6 +32,7 @@ typedef struct
uint32_t checksum = 0;
} persistenceData_t;
extern persistenceData_t PersistenceData;
typedef enum
{
BATTERY_UNDEFINED,
@@ -40,22 +43,36 @@ typedef enum
const char BatteryString[][10]{
"Undefined",
"LiPo 2S",
"LiPo 3S"
};
"LiPo 3S"};
const size_t BatteryString_Elements = sizeof(BatteryString) / sizeof(BatteryString[0]);
typedef struct
{
uint8_t EEPROM_Version = 1;
batteryType_t batteryType = BATTERY_UNDEFINED;
uint32_t checksum = 0;
uint8_t EEPROM_Version;
batteryType_t batteryType;
bool active_faction_on_reboot;
char Faction_1_Name[33];
char Faction_2_Name[33];
char Faction_3_Name[33];
uint32_t checksum;
} configData_t;
extern configData_t ConfigData;
const configData_t ConfigData_defaults = {
0, BATTERY_LIPO_3S, 0
2, // EEPROM_Version (incerease this if anything on Layout changes!)
BATTERY_LIPO_3S, // batteryType
false, // active_faction_on_reboot
"FACTION 1", // Faction_1_Name
"FACTION 2", // Faction_2_Name
"FACTION 3", // Faction_3_Name
0 // checksum
};
const uint16_t startofConfigData = 16;
const uint16_t startofPersistence = 16 + sizeof(ConfigData) + (sizeof(ConfigData) % 16);
void InitEEPROM();
void EEPROM_Process();
void StoreConfig_EEPROM();
@@ -69,6 +86,4 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
void MovePersistencePage_EEPROM(boolean reset);
uint32_t ConfigSanityCheck(bool autocorrect = false);
extern configData_t ConfigData;
extern persistenceData_t PersistenceData;
#endif // _CONFIG_H_
#endif // _EEPROM_H_

View File

@@ -5,6 +5,7 @@
typedef enum eSystem_Status
{
sysStat_null,
sysStat_Startup,
sysStat_Normal,
sysStat_Error,
@@ -12,6 +13,7 @@ typedef enum eSystem_Status
} tSystem_Status;
const char sSystem_Status_txt[][9] = {
"Null",
"Startup",
"Normal",
"Error",
@@ -43,6 +45,7 @@ typedef struct Globals_s
bool hasDTC;
int loadvoltage_mV = 0;
int battery_level = 0;
bool timer_disabled = false;
} Globals_t;
extern Globals_t globals;
@@ -56,8 +59,8 @@ typedef struct Constants_s
} Constants_t;
const Constants_t constants PROGMEM = {
1,2, // Firmware_Version
1,2, // Required Flash Version
1,3, // Firmware_Version
1,3, // Required Flash Version
GIT_REV // Git-Hash-String
};

View File

@@ -2,10 +2,16 @@
#define _LORA_NET_H_
#include <Arduino.h>
#ifdef LORA_FEATURE_ENABLED
#include <LoRa_E220.h>
#elif defined(FEATURE_ENABLE_UARTLORA)
#include <SoftwareSerial.h>
#endif
// local includes
#include "lora_messages.h"
#include "debugger.h"
#include "defaults.h"
#include "config.h"
#include "globals.h"

View File

@@ -6,7 +6,7 @@
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "globals.h"
#include "config.h"
#include "eeprom.h"
#define OLED_SDA 4
#define OLED_SCL 15

View File

@@ -14,6 +14,9 @@
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
#endif
#if defined(FEATURE_ENABLE_UARTLORA) && defined(FEATURE_ENABLE_LORA)
#error "You cannot enable LoRa and UART-Protocol at the same time!"
#endif
#ifdef FEATURE_ENABLE_WIFI_CLIENT
#ifndef WIFI_CLIENT_PASSWORD

View File

@@ -11,7 +11,7 @@
#include <AsyncJson.h>
#include <ArduinoJson.h>
#include "config.h"
#include "eeprom.h"
#include "globals.h"
#include "dtc.h"
#include "common.h"

View File

@@ -22,24 +22,22 @@ upload_speed = 921600
;upload_port = 10.0.1.48
;upload_protocol = espota
;upload_flags =
; --auth=${wifi_cred.admin_password}
; --auth=${wifi_cred.ota_password}
build_flags=
!python git_rev_macro.py
-DATOMIC_FS_UPDATE
-DFEATURE_ENABLE_WIFI_CLIENT
;-DFEATURE_ENABLE_WIFI_CLIENT
;-DFEATURE_ENABLE_LORA
;-DCAPTIVE
-DFEATURE_ENABLE_UARTLORA
-DWIFI_AP_IP_GW=10,0,0,1
-DADMIN_PASSWORD=${wifi_cred.admin_password}
-DADMIN_PASSWORD=${wifi_cred.ota_password}
-DWIFI_CLIENT_SSID=${wifi_cred.wifi_client_ssid}
-DWIFI_CLIENT_PASSWORD=${wifi_cred.wifi_client_password}
-DWIFI_AP_SSID=${wifi_cred.wifi_ap_ssid}
-DWIFI_AP_PASSWORD=${wifi_cred.wifi_ap_password}
-DDEVICE_NAME='"Dark Emergency Timer"'
-DFACTION_1_NAME='"GOF"'
-DFACTION_2_NAME='"KGG"'
-DFACTION_3_NAME='"MILIZ"'
;build_type = debug

View File

@@ -293,7 +293,7 @@ void Debug_printHelp()
{
char buff[64];
for (int i = sizeof(helpCmd) / 63; i < sizeof(helpCmd) / 63; i++)
for (unsigned int i = sizeof(helpCmd) / 63; i < sizeof(helpCmd) / 63; i++)
{
memcpy_P(buff, (helpCmd + (i * 63)), 63);
buff[63] = 0;

View File

@@ -1,25 +1,28 @@
#include "config.h"
#include "eeprom.h"
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
I2C_eeprom ee(I2C_EE_ADDRESS, EEPROM_SIZE_BYTES);
configData_t ConfigData;
persistenceData_t PersistenceData;
const uint16_t eeVersion = 1; // inc
boolean eeAvailable = false;
bool eeAvailable = false;
const uint16_t startofConfigData = 16;
const uint16_t startofPersistence = 16 + sizeof(ConfigData) + (sizeof(ConfigData) % 16);
boolean checkEEPROMavailable();
bool checkEEPROMavailable();
bool ValidateEEPROM_Version();
bool MigrateEEPROM(uint8_t fromVersion);
void InitEEPROM()
{
ee.begin();
checkEEPROMavailable();
eeAvailable = checkEEPROMavailable();
eeAvailable = ValidateEEPROM_Version();
Serial.printf("Initialized EEPROM at Address 0x%02X\n", I2C_EE_ADDRESS);
}
void EEPROM_Process()
{
if (eeAvailable == false)
return;
switch (globals.requestEEAction)
{
case EE_CFG_SAVE:
@@ -73,17 +76,18 @@ void EEPROM_Process()
void StoreConfig_EEPROM()
{
if (eeAvailable == false)
return;
ConfigData.checksum = 0;
ConfigData.checksum = Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData));
if (!checkEEPROMavailable())
return;
ee.updateBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData));
}
void GetConfig_EEPROM()
{
if (!checkEEPROMavailable())
if (eeAvailable == false)
return;
ee.readBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData));
@@ -108,6 +112,9 @@ void GetConfig_EEPROM()
void StorePersistence_EEPROM()
{
if (eeAvailable == false)
return;
if (PersistenceData.writeCycleCounter >= 0xFFF0)
MovePersistencePage_EEPROM(false);
else
@@ -116,15 +123,12 @@ void StorePersistence_EEPROM()
PersistenceData.checksum = 0;
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
if (!checkEEPROMavailable())
return;
ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
}
void GetPersistence_EEPROM()
{
if (!checkEEPROMavailable())
if (eeAvailable == false)
return;
ee.readBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
@@ -153,22 +157,29 @@ void GetPersistence_EEPROM()
void FormatConfig_EEPROM()
{
if (eeAvailable == false)
return;
Serial.println("Formatting Config-Partition");
ConfigData = ConfigData_defaults;
ConfigData.EEPROM_Version = eeVersion;
StoreConfig_EEPROM();
GetConfig_EEPROM();
}
void FormatPersistence_EEPROM()
{
if (eeAvailable == false)
return;
Serial.println("Formatting Persistance-Partition");
memset(&PersistenceData, 0, sizeof(PersistenceData));
PersistenceData = {0};
StorePersistence_EEPROM();
GetPersistence_EEPROM();
}
void MovePersistencePage_EEPROM(boolean reset)
{
if (!checkEEPROMavailable())
if (eeAvailable == false)
return;
globals.eePersistanceAdress = +sizeof(PersistenceData);
@@ -206,7 +217,7 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
{
#define BLOCK_TO_LENGTH 16
if (!checkEEPROMavailable())
if (eeAvailable == false)
return;
char ascii_buf[BLOCK_TO_LENGTH + 1];
@@ -236,15 +247,13 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
Serial.println();
}
boolean checkEEPROMavailable()
bool checkEEPROMavailable()
{
if (!ee.isConnected())
{
MaintainDTC(DTC_NO_EEPROM_FOUND, DTC_CRITICAL, true);
globals.systemStatus = sysStat_Error;
return false;
}
MaintainDTC(DTC_NO_EEPROM_FOUND, DTC_CRITICAL, false);
return true;
}
@@ -261,3 +270,89 @@ uint32_t ConfigSanityCheck(bool autocorrect)
return setting_reset_bits;
}
bool ValidateEEPROM_Version()
{
if (eeAvailable == false)
return false;
uint8_t EEPROMVersionOnChip = ee.readByte(startofConfigData);
if (EEPROMVersionOnChip < ConfigData_defaults.EEPROM_Version)
{
Serial.printf("EEPROM Image Version is %d, but %d expected - trying to migrate\n", EEPROMVersionOnChip, ConfigData_defaults.EEPROM_Version);
if (!MigrateEEPROM(EEPROMVersionOnChip))
{
Serial.print("Error\n");
MaintainDTC(DTC_EEPROM_MIGRATE_FAILED, DTC_CRITICAL, true, EEPROMVersionOnChip);
return false;
}
else
{
Serial.print("Success\n");
}
}
return true;
}
bool MigrateEEPROM(uint8_t fromVersion)
{
uint16_t persistanceMarker_onChip;
switch (fromVersion)
{
// Version 1 EEPROM Layout: startAdress size (byte)
// const uint16_t startofConfigData = 16 16
// const uint16_t startofPersistence = 32 24
//
// typedef struct
// {
// uint8_t EEPROM_Version = 1; 16 1
// batteryType_t batteryType = BATTERY_UNDEFINED; 17 4
// bool active_faction_on_reboot = false; 21 1
// uint32_t checksum = 0; 22 4
// } configData_t;
//
// typedef struct offset
// {
// uint32_t writeCycleCounter = 0; 0 4
// uint32_t faction_1_timer = 0; 4 4
// uint32_t faction_2_timer = 0; 8 4
// uint32_t faction_3_timer = 0; 12 4
// factions_t activeFaction = NONE; 16 4
// uint32_t checksum = 0; 20 4
// } persistenceData_t;
case 1:
// Migrate Persistance-Data
ee.readBlock(0, (uint8_t *)&persistanceMarker_onChip, sizeof(uint16_t));
if (persistanceMarker_onChip < startofPersistence)
{
ee.readBlock(persistanceMarker_onChip + 0, (uint8_t *)&PersistenceData.writeCycleCounter, 4);
ee.readBlock(persistanceMarker_onChip + 4, (uint8_t *)&PersistenceData.faction_1_timer, 4);
ee.readBlock(persistanceMarker_onChip + 8, (uint8_t *)&PersistenceData.faction_2_timer, 4);
ee.readBlock(persistanceMarker_onChip + 12, (uint8_t *)&PersistenceData.faction_3_timer, 4);
ee.readBlock(persistanceMarker_onChip + 16, (uint8_t *)&PersistenceData.activeFaction, 4);
ee.readBlock(persistanceMarker_onChip + 20, (uint8_t *)&PersistenceData.checksum, 4);
MovePersistencePage_EEPROM(true);
StorePersistence_EEPROM();
}
// Migrate Config-Data and set defaults for Values which doesn't exists in this earlier Version
ConfigData.EEPROM_Version = ConfigData_defaults.EEPROM_Version;
strncpy(ConfigData.Faction_1_Name, ConfigData_defaults.Faction_1_Name, sizeof(ConfigData.Faction_1_Name));
strncpy(ConfigData.Faction_2_Name, ConfigData_defaults.Faction_2_Name, sizeof(ConfigData.Faction_2_Name));
strncpy(ConfigData.Faction_3_Name, ConfigData_defaults.Faction_3_Name, sizeof(ConfigData.Faction_3_Name));
ee.readBlock(17, (uint8_t *)&ConfigData.batteryType, 4);
ee.readBlock(21, (uint8_t *)&ConfigData.active_faction_on_reboot, 1);
StoreConfig_EEPROM();
return true;
break;
default:
return false;
break;
}
}

View File

@@ -1,13 +1,19 @@
#include "lora_net.h"
#ifdef FEATURE_ENABLE_LORA
LoRa_E220 e220ttl(GPIO_LORA_TX, GPIO_LORA_RX, GPIO_LORA_AUX, 3, 4); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
void printParameters(struct Configuration configuration);
void printModuleInformation(struct ModuleInformation moduleInformation);
#elif defined(FEATURE_ENABLE_UARTLORA)
SoftwareSerial SerialLoRa(GPIO_LORA_RX, GPIO_LORA_TX); // RX, TX
void Parse_LoRa_UartCommand(char input[], int size);
#endif
bool InitLoRa(void (*MPinHelper)(int, int))
{
bool returnval;
bool returnval = false;
#ifdef FEATURE_ENABLE_LORA
e220ttl.setMPins = MPinHelper;
returnval = e220ttl.begin();
@@ -60,11 +66,15 @@ bool InitLoRa(void (*MPinHelper)(int, int))
{
MaintainDTC(DTC_NO_LORA_FOUND, DTC_WARN, true);
}
#elif defined(FEATURE_ENABLE_UARTLORA)
SerialLoRa.begin(9600);
#endif
return returnval;
}
void LoRa_Process()
{
#ifdef FEATURE_ENABLE_LORA
if (e220ttl.available() > 1)
{
ResponseContainer rc = e220ttl.receiveMessageRSSI();
@@ -82,10 +92,50 @@ void LoRa_Process()
Serial.println(rc.rssi, DEC);
}
}
#elif defined(FEATURE_ENABLE_UARTLORA)
char packageInput[16];
bool packageRecieved = false;
unsigned int bufferPtr = 0;
if (SerialLoRa.available() && packageRecieved == false)
{
while (bufferPtr < sizeof(packageInput))
{
packageInput[bufferPtr] = SerialLoRa.read();
if (packageInput[bufferPtr] == '\n')
{
packageInput[bufferPtr] = 0; // terminate String
packageRecieved = true;
Debug_pushMessage("Got LoRa UART: %s\n", packageInput);
break;
}
else if ((packageInput[bufferPtr] >= 0x30) || (packageInput[bufferPtr] <= 0x5A)) // only accept Numbers, UpperCase-Letters and some special chars
{
if (bufferPtr < sizeof(packageInput) - 1)
{
bufferPtr++;
}
else
{
packageInput[bufferPtr] = 0; // terminate String, bc Buffer is full (package to long)
packageRecieved = true; // send it anyway to the parser
Debug_pushMessage("Got LoRa UART: %s\n", packageInput);
break;
}
}
}
}
if (packageRecieved)
Parse_LoRa_UartCommand(packageInput, bufferPtr);
#endif
}
void sendStatus_LoRa()
{
#ifdef FEATURE_ENABLE_LORA
struct
{
MessageType_t type = "STATUS";
@@ -101,8 +151,25 @@ void sendStatus_LoRa()
ResponseStatus rs = e220ttl.sendFixedMessage(0xFF, 0xFF, 23, (byte *)&sendStatus, sizeof(sendStatus));
Serial.println(rs.getResponseDescription());
#elif defined(FEATURE_ENABLE_UARTLORA)
SerialLoRa.print(PersistenceData.faction_1_timer);
SerialLoRa.write(";");
SerialLoRa.print(PersistenceData.faction_2_timer);
SerialLoRa.write(";");
SerialLoRa.print(PersistenceData.faction_3_timer);
SerialLoRa.write(";");
SerialLoRa.print(PersistenceData.activeFaction);
SerialLoRa.write(";");
SerialLoRa.print(globals.battery_level);
SerialLoRa.write('\n');
#endif
}
#ifdef FEATURE_ENABLE_LORA
void printParameters(struct Configuration configuration)
{
Serial.println("----------------------------------------");
@@ -169,3 +236,70 @@ void printParameters(struct Configuration configuration)
Serial.println("----------------------------------------");
}
#endif
#ifdef FEATURE_ENABLE_UARTLORA
void Parse_LoRa_UartCommand(char input[], int size)
{
char delimiter[] = ";";
char *ptr;
char command[8];
char value[8];
ptr = strtok(input, delimiter);
while (ptr != NULL)
{
strncpy(command, ptr, sizeof(command));
ptr = strtok(NULL, delimiter);
strncpy(value, ptr, sizeof(value));
}
Debug_pushMessage("Parsed LoRa UART Command: %s Value: %s\n", command, value);
if (!strcmp(command, "ENABLE"))
{
globals.timer_disabled = false;
}
else if (!strcmp(command, "DISABLE"))
{
globals.timer_disabled = false;
}
else if (!strcmp(command, "RESET"))
{
PersistenceData.activeFaction = NONE;
PersistenceData.faction_1_timer = 0;
PersistenceData.faction_2_timer = 0;
PersistenceData.faction_3_timer = 0;
}
else if (!strcmp(command, "TMRSTP"))
{
PersistenceData.activeFaction = NONE;
}
else if (!strcmp(command, "TMR1"))
{
PersistenceData.faction_1_timer = atol(value);
}
else if (!strcmp(command, "TMR2"))
{
PersistenceData.faction_2_timer = atol(value);
}
else if (!strcmp(command, "TMR3"))
{
PersistenceData.faction_3_timer = atol(value);
}
else if (!strcmp(command, "EFAC1"))
{
PersistenceData.activeFaction = FACTION_1;
}
else if (!strcmp(command, "EFAC2"))
{
PersistenceData.activeFaction = FACTION_2;
}
else if (!strcmp(command, "EFAC3"))
{
PersistenceData.activeFaction = FACTION_3;
}
}
#endif

View File

@@ -19,7 +19,7 @@
#include "globals.h"
#include "dtc.h"
#include "debugger.h"
#ifdef FEATURE_ENABLE_LORA
#if defined(FEATURE_ENABLE_LORA) || defined(FEATURE_ENABLE_UARTLORA)
#include "lora_net.h"
#endif
@@ -47,8 +47,9 @@ void SetBatteryType(batteryType_t type);
void ProcessKeyCombos(bool *btnState);
void OverrideDisplay(uint32_t time, const char *message1, const char *message2, const char *message3);
void initGlobals();
void maintainSysStat();
#ifdef FEATURE_ENABLE_LORA
#if defined(FEATURE_ENABLE_UARTLORA) || defined(FEATURE_ENABLE_LORA)
void setMPins_Helper(int pin, int status);
void tmrCallback_StatusSender();
Ticker tmrStatusSender(tmrCallback_StatusSender, 30000, 0, MILLIS);
@@ -71,7 +72,7 @@ Ticker tmrWiFiMaintainConnection(tmrCallback_WiFiMaintainConnection, 1000, 0, MI
uint32_t DisplayOverrideFlag = 0;
char DisplayOverrideValue[3][5] = {0};
#ifdef FEATURE_ENABLE_LORA
#if defined(FEATURE_ENABLE_UARTLORA) || defined(FEATURE_ENABLE_LORA)
void setMPins_Helper(int pin, int status)
{
i2c_io.write(pin, status);
@@ -98,7 +99,6 @@ void setup()
InitEEPROM();
GetConfig_EEPROM();
GetPersistence_EEPROM();
Serial.print("EE-Init done\n");
if (i2c_io.begin())
{
@@ -119,7 +119,7 @@ void setup()
Serial.print("INA219 not Initialized\n");
}
#ifdef FEATURE_ENABLE_LORA
#if defined(FEATURE_ENABLE_UARTLORA) || defined(FEATURE_ENABLE_LORA)
if (InitLoRa(&setMPins_Helper))
{
Serial.print("Initialized LoRa_Transceiver\n");
@@ -207,11 +207,15 @@ void setup()
tmrFactionTicker.start();
tmrInputGetter.start();
if (ConfigData.active_faction_on_reboot == false)
PersistenceData.activeFaction = NONE;
Serial.print("\nSetup Done\n");
}
void loop()
{
maintainSysStat();
tmrEEPROMCyclicPDS.update();
tmrFactionTicker.update();
@@ -225,9 +229,9 @@ void loop()
DTC_Process();
Debug_Process();
#ifdef FEATURE_ENABLE_LORA
tmrStatusSender.update();
#if defined(FEATURE_ENABLE_LORA) || defined(FEATURE_ENABLE_UARTLORA)
LoRa_Process();
tmrStatusSender.update();
#endif
#ifdef CAPTIVE
@@ -237,27 +241,6 @@ void loop()
tmrWiFiMaintainConnection.update();
#endif
switch (globals.systemStatus)
{
case sysStat_Error:
/* code */
break;
case sysStat_Normal:
/* code */
break;
case sysStat_Shutdown:
OverrideDisplay(SHUTDOWN_DELAY_MS , " re", "boot", " ");
SystemShutdown();
break;
case sysStat_Startup:
if (millis() > STARTUP_DELAY_MS)
globals.systemStatus = sysStat_Normal;
break;
default:
break;
}
yield();
}
@@ -306,25 +289,28 @@ void SevenSeg_Output()
disp_FAC_1.refresh();
snprintf(sevenSegBuff, sizeof(sevenSegBuff), "%4d", PersistenceData.faction_1_timer / 60);
disp_FAC_1.display(String(sevenSegBuff), false, false);
disp_FAC_1.setDp((PersistenceData.activeFaction == FACTION_1) && (millis() % 1000 > 500));
disp_FAC_1.setDp((PersistenceData.activeFaction == FACTION_1) && (millis() % 1000 > 500) ? 0x08 : 0x00);
disp_FAC_2.setBrightness(PersistenceData.activeFaction == FACTION_2 ? 5 : 1);
disp_FAC_2.refresh();
snprintf(sevenSegBuff, sizeof(sevenSegBuff), "%4d", PersistenceData.faction_2_timer / 60);
disp_FAC_2.display(String(sevenSegBuff), false, false);
disp_FAC_1.setDp((PersistenceData.activeFaction == FACTION_2) && (millis() % 1000 > 500));
disp_FAC_2.setDp((PersistenceData.activeFaction == FACTION_2) && (millis() % 1000 > 500) ? 0x08 : 0x00);
disp_FAC_3.setBrightness(PersistenceData.activeFaction == FACTION_3 ? 5 : 1);
disp_FAC_3.refresh();
snprintf(sevenSegBuff, sizeof(sevenSegBuff), "%4d", PersistenceData.faction_3_timer / 60);
disp_FAC_3.display(String(sevenSegBuff), false, false);
disp_FAC_1.setDp((PersistenceData.activeFaction == FACTION_3) && (millis() % 1000 > 500));
disp_FAC_3.setDp((PersistenceData.activeFaction == FACTION_3) && (millis() % 1000 > 500) ? 0x08 : 0x00);
}
}
}
void tmrCallback_FactionTicker()
{
if (globals.timer_disabled == true)
PersistenceData.activeFaction = NONE;
switch (PersistenceData.activeFaction)
{
case FACTION_1:
@@ -361,40 +347,43 @@ void tmrCallback_InputGetter()
if (keysPressed > 1)
{
Serial.println("ERROR: More than one Flag active - setting no Faction active");
Debug_pushMessage("ERROR: More than one Flag active - setting no Faction active");
PersistenceData.activeFaction = NONE;
return;
}
if (btnState[0] == FAC_1_TRG_PRESSED)
if (btnState[0] == FAC_1_TRG_PRESSED && globals.timer_disabled == false)
{
if (PersistenceData.activeFaction != FACTION_1)
{
Serial.println("Faction 1 captured !");
Debug_pushMessage("Faction 1 captured !");
globals.requestEEAction = EE_PDS_SAVE;
}
PersistenceData.activeFaction = FACTION_1;
}
if (btnState[1] == FAC_2_TRG_PRESSED)
if (btnState[1] == FAC_2_TRG_PRESSED && globals.timer_disabled == false)
{
if (PersistenceData.activeFaction != FACTION_2)
{
Serial.println("Faction 2 captured !");
Debug_pushMessage("Faction 2 captured !");
globals.requestEEAction = EE_PDS_SAVE;
}
PersistenceData.activeFaction = FACTION_2;
}
if (btnState[2] == FAC_3_TRG_PRESSED)
if (btnState[2] == FAC_3_TRG_PRESSED && globals.timer_disabled == false)
{
if (PersistenceData.activeFaction != FACTION_3)
{
Serial.println("Faction 3 captured !");
Debug_pushMessage("Faction 3 captured !");
globals.requestEEAction = EE_PDS_SAVE;
}
PersistenceData.activeFaction = FACTION_3;
}
}
#ifdef FEATURE_ENABLE_LORA
#if defined(FEATURE_ENABLE_LORA) || defined(FEATURE_ENABLE_UARTLORA)
void tmrCallback_StatusSender()
{
sendStatus_LoRa();
@@ -578,17 +567,17 @@ void ProcessKeyCombos(bool *btnState)
if (btnState[0] != FAC_1_TRG_PRESSED && keyStatus_Fac1 == KEY_PRESSED)
{
if (keyCount_Fac2 > 0 || keyCount_Fac3 > 0)
Serial.printf("KeyCombo 2: %d | 3: %d\n", keyCount_Fac2, keyCount_Fac3);
Debug_pushMessage("KeyCombo 2: %d | 3: %d\n", keyCount_Fac2, keyCount_Fac3);
if (keyCount_Fac2 == 2 && keyCount_Fac3 == 0)
{
Serial.println("KeyCombo: WiFi AP ON");
Debug_pushMessage("KeyCombo: WiFi AP ON");
OverrideDisplay(5000, "NET ", " ", " ");
toggleWiFiAP(false);
}
else if (keyCount_Fac2 == 4 && keyCount_Fac3 == 0)
{
Serial.printf("KeyCombo: Reset Timer\n");
Debug_pushMessage("KeyCombo: Reset Timer\n");
if (globals.systemStatus == sysStat_Startup)
{
OverrideDisplay(5000, "RST ", " ", " ");
@@ -601,7 +590,7 @@ void ProcessKeyCombos(bool *btnState)
else
{
OverrideDisplay(5000, "ERR ", " ", " ");
Serial.printf("ERROR: only %d seconds after Startup!\n", STARTUP_DELAY_MS / 1000);
Debug_pushMessage("ERROR: only %d seconds after Startup!\n", STARTUP_DELAY_MS / 1000);
}
}
@@ -612,3 +601,51 @@ void ProcessKeyCombos(bool *btnState)
keyStatus_Fac3 = KEY_RELEASED;
}
}
void maintainSysStat()
{
static tSystem_Status lastStat = sysStat_null;
// system Status Transistions
switch (globals.systemStatus)
{
case sysStat_Shutdown:
SystemShutdown();
break;
case sysStat_Startup:
if (millis() > STARTUP_DELAY_MS)
globals.systemStatus = sysStat_Normal;
break;
case sysStat_Error:
case sysStat_Normal:
case sysStat_null:
default:
break;
}
// system Status Changed Actions
if (lastStat != globals.systemStatus)
{
switch (globals.systemStatus)
{
case sysStat_Shutdown:
OverrideDisplay(SHUTDOWN_DELAY_MS, " re", "boot", " ");
break;
case sysStat_Startup:
OverrideDisplay(STARTUP_DELAY_MS, "star", "t up", " ");
break;
case sysStat_Error:
case sysStat_Normal:
case sysStat_null:
default:
break;
}
lastStat = globals.systemStatus;
}
}

View File

@@ -33,10 +33,10 @@ void OLED_Process()
display.setCursor(0, 0);
display.printf("LiPo: %d%%\n", globals.battery_level);
display.print(PersistenceData.activeFaction == FACTION_1 ? "> " : " ");
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_1_NAME, PersistenceData.faction_1_timer / 3600, (PersistenceData.faction_1_timer / 60) % 60, PersistenceData.faction_1_timer % 60);
display.printf("%-5s: %02d:%02d:%02d\n", PersistenceData.faction_1_timer, PersistenceData.faction_1_timer / 3600, (PersistenceData.faction_1_timer / 60) % 60, PersistenceData.faction_1_timer % 60);
display.print(PersistenceData.activeFaction == FACTION_2 ? "> " : " ");
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_2_NAME, PersistenceData.faction_2_timer / 3600, (PersistenceData.faction_2_timer / 60) % 60, PersistenceData.faction_2_timer % 60);
display.printf("%-5s: %02d:%02d:%02d\n", PersistenceData.faction_2_timer, PersistenceData.faction_2_timer / 3600, (PersistenceData.faction_2_timer / 60) % 60, PersistenceData.faction_2_timer % 60);
display.print(PersistenceData.activeFaction == FACTION_3 ? "> " : " ");
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_3_NAME, PersistenceData.faction_3_timer / 3600, (PersistenceData.faction_3_timer / 60) % 60, PersistenceData.faction_3_timer % 60);
display.printf("%-5s: %02d:%02d:%02d\n", PersistenceData.faction_3_timer, PersistenceData.faction_3_timer / 3600, (PersistenceData.faction_3_timer / 60) % 60, PersistenceData.faction_3_timer % 60);
display.display();
}

View File

@@ -84,6 +84,8 @@ String processor(const String &var)
return String(globals.battery_level);
if (var == "DEVICENAME")
return String(globals.DeviceName);
if (var == "DEVICENAME_ID")
return String(globals.DeviceName_ID);
if (var == "BATTERY_TYPE")
return String(ConfigData.batteryType);
if (var == "BAT_VOLTAGE")
@@ -180,14 +182,21 @@ String processor(const String &var)
if (var == "ACTIVE_FACTION")
return String(PersistenceData.activeFaction);
if (var == "FACTION_1_ACTIVE")
return String(PersistenceData.activeFaction == FACTION_1 ? "bg-primary" : "bg-secondary");
if (var == "FACTION_2_ACTIVE")
return String(PersistenceData.activeFaction == FACTION_2 ? "bg-primary" : "bg-secondary");
if (var == "FACTION_3_ACTIVE")
return String(PersistenceData.activeFaction == FACTION_3 ? "bg-primary" : "bg-secondary");
if (var == "NAME_FAC_1")
return FACTION_1_NAME;
return String(ConfigData.Faction_1_Name);
if (var == "NAME_FAC_2")
return FACTION_2_NAME;
return String(ConfigData.Faction_2_Name);
if (var == "NAME_FAC_3")
return FACTION_3_NAME;
return String(ConfigData.Faction_3_Name);
if (var == "BATTERY_SELECT_OPTIONS")
{
@@ -200,6 +209,12 @@ String processor(const String &var)
return temp;
}
if (var == "FACTIONREBOOT_CHECKED")
return String(ConfigData.active_faction_on_reboot == true ? "checked" : "");
if (var == "FACTION_RECOVERY")
return String(ConfigData.active_faction_on_reboot);
return String();
}
@@ -256,6 +271,30 @@ void WebserverPOST_Callback(AsyncWebServerRequest *request)
ConfigData.batteryType = temp;
}
if (request->hasParam("factionreboot_cont", true))
{
AsyncWebParameter *param = request->getParam("factionreboot_cont", true);
if (param->value() == "on")
ConfigData.active_faction_on_reboot = true;
}
else
{
ConfigData.active_faction_on_reboot = false;
}
if (p->name() == "faction_1_name")
{
strncpy(ConfigData.Faction_1_Name, p->value().c_str(), sizeof(ConfigData.Faction_1_Name));
}
if (p->name() == "faction_2_name")
{
strncpy(ConfigData.Faction_2_Name, p->value().c_str(), sizeof(ConfigData.Faction_2_Name));
}
if (p->name() == "faction_3_name")
{
strncpy(ConfigData.Faction_3_Name, p->value().c_str(), sizeof(ConfigData.Faction_3_Name));
}
if (p->name() == "settingssave")
globals.requestEEAction = EE_CFG_SAVE;
// end: POST Form Settings
@@ -368,6 +407,9 @@ void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &f
ConfigData.batteryType = (batteryType_t)doc["config"]["batteryType"].as<uint32_t>();
ConfigData.EEPROM_Version = doc["config"]["EEPROM_Version"].as<uint32_t>();
strncpy(ConfigData.Faction_1_Name, doc["config"]["Faction_1_Name"].as<String>().c_str(), sizeof(ConfigData.Faction_1_Name));
strncpy(ConfigData.Faction_2_Name, doc["config"]["Faction_2_Name"].as<String>().c_str(), sizeof(ConfigData.Faction_2_Name));
strncpy(ConfigData.Faction_3_Name, doc["config"]["Faction_3_Name"].as<String>().c_str(), sizeof(ConfigData.Faction_3_Name));
PersistenceData.writeCycleCounter = doc["persis"]["writeCycleCounter"].as<uint16_t>();
PersistenceData.activeFaction = (factions_t)doc["persis"]["activeFaction"].as<uint32_t>();
@@ -417,6 +459,9 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
config["EEPROM_Version"] = ConfigData.EEPROM_Version;
config["batteryType"] = ConfigData.batteryType;
config["Faction_1_Name"] = ConfigData.Faction_1_Name;
config["Faction_2_Name"] = ConfigData.Faction_2_Name;
config["Faction_3_Name"] = ConfigData.Faction_3_Name;
sprintf(buffer, "0x%08X", ConfigData.checksum);
config["checksum"] = buffer;

View File

@@ -1,6 +1,6 @@
[wifi_cred]
wifi_ap_ssid = wifi-ap-ssid
wifi_ap_password = wifiappass
wifi_ssid = wifi-ssid
wifi_password = wifi-pass
admin_password = ota-password
wifi_client_ssid = wifi-ssid
wifi_client_password = wifi-pass
ota_password = ota-password