Skip to content

Commit 3ec934f

Browse files
authored
New config structure, load & save (#177)
- Create and document a new clean JSON for the configuration fixes #118 - Config format is structured json this allows: - PrivacyAreas are stored as array inside Json (not a properties with counter in the property name) - SensorOffstes are stored as array inside Json - Main config is inside a array which is prepared to hold different config profiles for certain values. - Configuration file is not re-written at each OBS restart, only ServerMode writes config - A backup of the configuration is created before writing the new config (might be dropped again SPIFFS if memory gets low) - If the current config can not be read from SPIFFS the backup is loaded if possible - Old config format is still accepted in backup/restore dialog - Some values had been dropped / replaced - hostname / port, is not used now a PORTAL_URL is added (still not used) - obsUsreId is now called PORTAL_TOKEN which is more reflecting the use - gpsFix, now has 3 states: `FIX_POS`, `FIX_TIME` and `FIX_NO_WAIT` - Lot of changes are preparations only for further changes It is a good idea to make a backup of your configuration before updating.
1 parent 5c19ee5 commit 3ec934f

File tree

11 files changed

+745
-594
lines changed

11 files changed

+745
-594
lines changed

docs/software/firmware/obs_cfg.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# OpenBikeSensor configuration
2+
3+
This file describes the configuration format of the OBS internal(!)
4+
configuration file. Please note that even that the format seems well
5+
documented, it is considered an internal format which might change at
6+
any time. There might be interpretations possible in which case
7+
the current implementation defines the correct used.
8+
9+
The configuration is prepared for extension to support configuration
10+
presets, where certain values of the "default" configuration can be
11+
changed for a certain presets. The handle bar offsets are very likely
12+
candidates for this. The Wi-Fi or Portal configuration is more likely
13+
not part of a presets.
14+
15+
When working with backups please note that the configuration file contains
16+
your Wi-Fi password, and the portal token in plain text.
17+
Both values are secrets that should not be disclosed, so keep the backup
18+
at a save place and replace these values when sharing.
19+
20+
## cfg.obs
21+
22+
Use the annotated sample file as documentation, order of the keys is not
23+
relevant put the order of the array content.
24+
25+
```json5
26+
{
27+
// obs must be an array. It can contain possibly multiple entries,
28+
// the 1st defines default values for all presets, and the default presets.
29+
"obs": [
30+
{
31+
// enables / disables bluetooth
32+
"bluetooth": true,
33+
// time window for overtake measurement confirmation
34+
"confirmationTimeSeconds": 4,
35+
// Bitfield for some internal developer features
36+
"devConfig": 0,
37+
// Bitfield display config, see DisplayOptions for details,
38+
// as noted all subject to change!
39+
"displayConfig": 15,
40+
// For what GPS fix should the OBS wait at startup?
41+
// -2: FIX POS; -1: Time only; 0: No wait
42+
"gpsFix": -2,
43+
// Textual name of the profile - waiting for fetures to come.
44+
"name": "default",
45+
// Name of the OBS, will be used for WiFo, Bluetooth and other places
46+
// currently no way to change it, consists of OpenBikeSensor-<deviceId>
47+
"obsName": "OpenBikeSensor-affe",
48+
// The handle bar offset in cm, order right, left.
49+
"offset": [
50+
31,
51+
32
52+
],
53+
// Token used to authenticate and authorize at the portal.
54+
"portalToken": "thisIsAlsoSecret",
55+
// URL of the portal to be used (currently it is hardcoded, the value is not used)
56+
"portalUrl": "https://openbikesensor.hlrs.de",
57+
// Array with privacy areas to be considered
58+
"privacyArea": [
59+
{
60+
// latitude of the entered value, for documentation and display purpose only
61+
"lat": 48.001,
62+
// shifted latitude used for position filtering
63+
"latT": 48.00105,
64+
// longitude of the entered value, for documentation and display purpose only
65+
"long": 9.001,
66+
// shifted longitude used for position filtering
67+
"longT": 9.001121,
68+
// radius in meters around the position to be filtered
69+
"radius": 101
70+
}
71+
],
72+
// Bitfield for the privacy configuration see PrivacyOptions
73+
"privacyConfig": 10,
74+
// Active preset - always 0 as of today
75+
"selectedPreset": 0,
76+
// Selects if the SimRa mode is activated
77+
"simRa": false,
78+
// Password of your Wi-Fi where the OBS should log into in server mode
79+
"wifiPassword": "swordfish",
80+
// SSID of your Wi-Fi where the OBS should log into in server mode
81+
"wifiSsid": "obs-cloud"
82+
}
83+
]
84+
}
85+
```
86+

platformio.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ upload_speed = 921600
2929
board_build.partitions = min_spiffs.csv
3030
; The following dependencies can either use their full name or their (platformio library) id
3131
lib_deps =
32-
; ArduinoJson by Benoit Blanchon
33-
ArduinoJson
32+
; https://arduinojson.org/v6/api/
33+
bblanchon/ArduinoJson @ ^6.17.2
3434
; CircularBuffer by AgileWare
3535
1796
3636
; TinyGPSPlus by Mikal Hart

src/OpenBikeSensorFirmware.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "OpenBikeSensorFirmware.h"
2222

23+
#include "SPIFFS.h"
24+
2325
#ifndef BUILD_NUMBER
2426
#define BUILD_NUMBER "local"
2527
#endif
@@ -63,7 +65,6 @@ unsigned long timeOfMinimum = esp_timer_get_time(); // millis();
6365
unsigned long startTimeMillis = 0;
6466
unsigned long currentTimeMillis = millis();
6567

66-
bool usingSD = false;
6768
String text = "";
6869
uint16_t minDistanceToConfirm = MAX_SENSOR_VALUE;
6970
uint16_t minDistanceToConfirmIndex = 0;
@@ -123,23 +124,25 @@ void setup() {
123124
displayTest->showTextOnGrid(2, 1, "Config... error ");
124125
return;
125126
}
126-
// Should load default config if run for the first time
127+
127128
Serial.println(F("Load config"));
128-
loadConfiguration(configFilename, config);
129+
ObsConfig cfg; // this one is valid in setup!
130+
if (!cfg.loadConfig()) {
131+
displayTest->showTextOnGrid(2, 1, "Config...RESET");
132+
delay(1000); // resetting config once, wait a moment
133+
}
129134

130135
// Dump config file
131-
Serial.println(F("Print config file..."));
132-
printConfig(config);
136+
log_d("Print config file...");
137+
cfg.printConfig();
133138

134-
// Save the config. This ensures, that new options exist as well
135-
saveConfiguration(configFilename, config);
139+
// TODO: Select Profile missing here or below!
140+
// Copy data to static view on config!
141+
cfg.fill(config);
136142

137-
#ifdef DEVELOP
138143
if(config.devConfig & ShowGrid) {
139144
displayTest->showGrid(true);
140145
}
141-
#endif
142-
143146
if (config.displayConfig & DisplayInvert) {
144147
displayTest->invert();
145148
} else {
@@ -201,7 +204,7 @@ void setup() {
201204

202205
delay(1000); // Added for user experience
203206

204-
startServer();
207+
startServer(&cfg);
205208
OtaInit(esp_chipid);
206209

207210
while (true) {
@@ -263,45 +266,50 @@ void setup() {
263266
voltageMeter = new VoltageMeter; // takes a moment, so do it here
264267

265268
delay(300);
269+
int gpsWaitFor = cfg.getProperty<int>(ObsConfig::PROPERTY_GPS_FIX);
266270
while (!validGPSData) {
267271
readGPSData();
268272

269-
switch (config.GPSConfig) {
270-
case ValidLocation: {
271-
validGPSData = gps.location.isValid();
273+
switch (gpsWaitFor) {
274+
case GPS::FIX_POS:
275+
validGPSData = gps.sentencesWithFix() > 0;
272276
if (validGPSData) {
273277
Serial.println("Got location...");
274278
}
275279
break;
276-
}
277-
case ValidTime: {
278-
validGPSData = gps.time.isValid();
280+
case GPS::FIX_TIME:
281+
validGPSData = gps.time.isValid()
282+
&& !(gps.time.second() == 00 && gps.time.minute() == 00 && gps.time.hour() == 00);
279283
if (validGPSData) {
280284
Serial.println("Got time...");
281285
}
282286
break;
283-
}
284-
case NumberSatellites: {
285-
validGPSData = gps.satellites.value() >= config.satsForFix;
287+
case GPS::FIX_NO_WAIT:
288+
validGPSData = true;
289+
if (validGPSData) {
290+
Serial.println("GPS, no wait");
291+
}
292+
break;
293+
default:
294+
validGPSData = gps.satellites.value() >= gpsWaitFor;
286295
if (validGPSData) {
287296
Serial.println("Got required number of satellites...");
288297
}
289298
break;
290-
}
291-
default: {
292-
validGPSData = false;
293-
}
294-
295299
}
296-
delay(300);
300+
delay(50);
297301

298302
String satellitesString;
299303
if (gps.passedChecksum() == 0) { // could not get any valid char from GPS module
300304
satellitesString = "OFF?";
301-
} else if (!gps.time.isValid()) {
305+
} else if (!gps.time.isValid()
306+
|| (gps.time.second() == 00 && gps.time.minute() == 00 && gps.time.hour() == 00)) {
302307
satellitesString = "no time";
303308
} else {
304-
satellitesString = String(gps.satellites.value()) + " / " + String(config.satsForFix) + " sats";
309+
char timeStr[32];
310+
snprintf(timeStr, sizeof(timeStr), "%02d:%02d:%02d %dsa",
311+
gps.time.hour(), gps.time.minute(), gps.time.second(), gps.satellites.value());
312+
satellitesString = String(timeStr);
305313
}
306314
displayTest->showTextOnGrid(2, 5, satellitesString);
307315

@@ -315,12 +323,6 @@ void setup() {
315323
}
316324
}
317325

318-
if (gps.satellites.value() >= config.satsForFix) {
319-
Serial.print("Got GPS Fix: ");
320-
Serial.println(String(gps.satellites.value()));
321-
displayTest->showTextOnGrid(2, 5, "Got GPS Fix");
322-
}
323-
324326
//##############################################################
325327
// Bluetooth
326328
//##############################################################
@@ -449,8 +451,8 @@ void loop() {
449451
} // end measureInterval while
450452

451453
// Write the minimum values of the while-loop to a set
452-
for (size_t idx = 0; idx < sensorManager->m_sensors.size(); ++idx) {
453-
currentSet->sensorValues.push_back(sensorManager->m_sensors[idx].minDistance);
454+
for (auto & m_sensor : sensorManager->m_sensors) {
455+
currentSet->sensorValues.push_back(m_sensor.minDistance);
454456
}
455457
currentSet->measurements = sensorManager->lastReadingCount;
456458
memcpy(&(currentSet->readDurationsRightInMicroseconds),
@@ -487,7 +489,7 @@ void loop() {
487489
// Empty buffer by writing it, after confirmation it will be written to SD card directly so no confirmed sets will be lost
488490
while (!dataBuffer.isEmpty() && dataBuffer.first() != datasetToConfirm) {
489491
DataSet* dataset = dataBuffer.shift();
490-
if (dataset->confirmedDistances.size() == 0) {
492+
if (dataset->confirmedDistances.empty()) {
491493
if (writer) {
492494
writer->append(*dataset);
493495
}

0 commit comments

Comments
 (0)