├── .gitattributes
├── src
├── fonts
│ ├── OpenSans-Regular_6.h
│ ├── OpenSans-Regular_7.h
│ ├── OpenSans-Regular_14.h
│ ├── OpenSans-Regular_15.h
│ ├── OpenSans-Regular_24.h
│ ├── OpenSans-Regular_26.h
│ ├── OpenSans-Regular_33.h
│ ├── OpenSans-Regular_37.h
│ ├── fonts.h
│ ├── README.md
│ ├── logos.h
│ └── LICENSE.txt
├── truststore
│ ├── x509_crt_bundle
│ └── README.md
├── sd-partition-table.csv
├── utils
│ ├── file.h
│ ├── https.h
│ ├── file.cpp
│ ├── button.h
│ ├── obsutils.h
│ ├── median.h
│ ├── alpdata.h
│ ├── timeutils.h
│ ├── streams.h
│ ├── button.cpp
│ ├── multipart.h
│ ├── streams.cpp
│ ├── obsutils.cpp
│ ├── multipart.cpp
│ ├── https.cpp
│ ├── timeutils.cpp
│ └── alpdata.cpp
├── OpenBikeSensorFirmware.h
├── Firmware.h
├── uploader.h
├── bluetooth
│ ├── BatteryService.cpp
│ ├── DeviceInfoService.cpp
│ ├── HeartRateService.h
│ ├── DeviceInfoService.h
│ ├── BatteryService.h
│ ├── HeartRateService.cpp
│ ├── ObsService.h
│ ├── _IBluetoothService.h
│ ├── BluetoothManager.h
│ ├── ObsService.cpp
│ └── BluetoothManager.cpp
├── configServer.h
├── globals.h
├── VoltageMeter.h
├── variant.h
├── writer.h
├── gpsrecord.h
├── gpsrecord.cpp
├── VoltageMeter.cpp
├── uploader.cpp
├── sensor.h
├── obsimprov.h
├── config.h
├── Firmware.cpp
├── logo.h
└── displays.cpp
├── .github
├── dependabot.yml
├── fake-cc
├── README-release.md
└── workflows
│ └── codeql-analysis.yml
├── .idea
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── vcs.xml
├── copyright
│ ├── profiles_settings.xml
│ └── openbikesensor_lgpl.xml
├── OpenBikeSensorFirmware.iml
├── runConfigurations
│ ├── PlatformIO_Only_Upload.xml
│ ├── PlatformIO_Build___Upload.xml
│ ├── PlatformIO_Debug.xml
│ └── Z_DUMMY_TARGET.xml
└── misc.xml
├── .editorconfig
├── open-bike-sensor.code-workspace
├── .gitignore
├── docs
└── software
│ └── firmware
│ ├── initial_flash.md
│ ├── obs_cfg.md
│ ├── bluetooth_services.md
│ └── csv_format.md
├── custom_config.ini.example
├── platformio.ini
└── LICENSE
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.h text eol=lf
3 | *.cpp text eol=lf
4 | *.ino text eol=lf
5 |
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_6.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_6.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_7.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_7.h
--------------------------------------------------------------------------------
/src/truststore/x509_crt_bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/truststore/x509_crt_bundle
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_14.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_14.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_15.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_15.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_24.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_24.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_26.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_26.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_33.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_33.h
--------------------------------------------------------------------------------
/src/fonts/OpenSans-Regular_37.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbikesensor/OpenBikeSensorFirmware/HEAD/src/fonts/OpenSans-Regular_37.h
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: /
5 | schedule:
6 | interval: weekly
7 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.github/fake-cc:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | /github/home/.platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-g++ \
4 | "$@" 2>&1 \
5 | | sed 's|: xtensa-esp32-elf|: le32-unknown-nacl|g' \
6 | | sed 's|=xtensa-esp32-elf|=le32-unknown-nacl|g'
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | [*]
5 | end_of_line = lf
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 |
9 | [*.{h,cpp,ino}]
10 | charset = utf-8
11 | indent_style = space
12 | indent_size = 2
13 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/OpenBikeSensorFirmware.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/truststore/README.md:
--------------------------------------------------------------------------------
1 | # Full TLS Truststore
2 |
3 | ## Generate / Update
4 |
5 | 1. curl --remote-name https://raw.githubusercontent.com/espressif/arduino-esp32/master/tools/gen_crt_bundle.py
6 | 1. curl --remote-name https://curl.se/ca/cacert.pem
7 | 1. python3 gen_crt_bundle.py --input cacert.pem
8 |
--------------------------------------------------------------------------------
/src/fonts/fonts.h:
--------------------------------------------------------------------------------
1 | #ifndef FONTS_H_
2 | #define FONTS_H_
3 |
4 | #include
5 |
6 | #include "OpenSans-Regular_6.h"
7 | #include "OpenSans-Regular_7.h"
8 | #include "OpenSans-Regular_14.h"
9 | #include "OpenSans-Regular_24.h"
10 | #include "OpenSans-Regular_33.h"
11 |
12 | #endif // FONTS_H_
13 |
--------------------------------------------------------------------------------
/open-bike-sensor.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {
8 | "files.associations": {
9 | "*.tpp": "cpp",
10 | "random": "cpp",
11 | "functional": "cpp",
12 | "cstdint": "cpp"
13 | }
14 | },
15 | "extensions": {
16 | "recommendations": [
17 | "platformio.platformio-ide",
18 | "editorconfig.editorconfig"
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/fonts/README.md:
--------------------------------------------------------------------------------
1 | # Fonts
2 |
3 | The `OpenSans-Regular_*` files in this directory were generated from
4 | [`OpenSans-Regular.ttf`](https://fonts.google.com/specimen/Open+Sans) using the following bash statement:
5 |
6 | ``` bash
7 | for i in 6 7 14 24 35; do
8 | otf2bdf OpenSans-Regular.ttf -p $i > OpenSans-Regular_$i.bdf
9 | u8g2/tools/font/bdfconv/bdfconv -f 1 -n OpenSans_Regular_$i -o OpenSans-Regular_$i.h OpenSans-Regular_$i.bdf
10 | done
11 | ```
12 |
--------------------------------------------------------------------------------
/src/sd-partition-table.csv:
--------------------------------------------------------------------------------
1 | # Using https://github.com/espressif/arduino-esp32/blob/master/tools/partitions/min_spiffs.csv
2 | # but with minimum ota_1 part size to get larger ota_0
3 | # Name, Type, SubType, Offset, Size, Flags
4 | nvs, data, nvs, 0x009000, 0x005000,
5 | otadata, data, ota, 0x00e000, 0x002000,
6 | app, app, ota_0, 0x010000, 0x380000,
7 | flashApp, app, ota_1, 0x390000, 0x040000,
8 | spiffs, data, spiffs, 0x3D0000, 0x030000,
--------------------------------------------------------------------------------
/.idea/runConfigurations/PlatformIO_Only_Upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/PlatformIO_Build___Upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/PlatformIO_Debug.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Z_DUMMY_TARGET.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/serialmonitor_settings.xml
2 | .idea/deployment.xml
3 | .idea/modules.xml
4 | .idea/compilerexplorer.settings.xml
5 | *esp32.bin
6 | .pio
7 | .vscode/.browse.c_cpp.db*
8 | .vscode/c_cpp_properties.json
9 | .vscode/launch.json
10 | .vscode/ipch
11 | .vscode/extensions.json
12 | .idea/sonarIssues.xml
13 | CMakeLists.txt
14 | CMakeListsPrivate.txt
15 | cmake-build-*/
16 | custom_config.ini
17 | !custom_config.ini.example
18 |
19 | # jekyll
20 | docs/_site
21 | docs/.sass-cache
22 | docs/.jekyll-cache
23 | docs/.jekyll-metadata
24 | docs/vendor
25 |
26 | .DS_Store
27 | .vscode
28 |
29 | # for people installing pio venv style
30 | venv
31 |
32 | # jetbrains
33 | .idea
--------------------------------------------------------------------------------
/docs/software/firmware/initial_flash.md:
--------------------------------------------------------------------------------
1 | # Initial ESP installation
2 |
3 | There are various ways to flash the ESP, if you are an expert feel
4 | free to choose whatever way you want. The official way to install
5 | the firmware via a browser. To do this open
6 | https://install.openbikesensor.org/ with either your Chrome or Edge browser
7 | and follow up from there.
8 |
9 | For a more none technical description of the process switch to
10 | https://www.openbikesensor.org/docs/firmware/.
11 |
12 | ## History
13 |
14 | You can see the old documentation with different variants in the former
15 | [documentation on github](https://github.com/openbikesensor/OpenBikeSensorFirmware/blob/v0.10.676/docs/software/firmware/initial_flash.md).
16 |
--------------------------------------------------------------------------------
/.github/README-release.md:
--------------------------------------------------------------------------------
1 | ## Release Build
2 |
3 | The github action creates a draft release for every build on the
4 | main branch. You can publish any release from the main branch
5 | as either "Pre-release" or final release upon publishing.
6 |
7 | Idea is to delete intermediate releases after a while manually.
8 |
9 | Version number major part is defined in
10 | `src/OpenBikeSensorFirmware.cpp` as OBSVersion.
11 | Just modify the static numeric part, the build script will take
12 | care for the rest.
13 |
14 | Format of the version follows https://semver.org the 3 segment
15 | is automatically increased with every build by github or for
16 | local builds is `-dev`. Also builds from a other branch than
17 | main get `-RC` as part of the version number.
18 |
19 | A typical main branch version looks like `v1.2.432` a build from
20 | any temporary branch is `v1.2-RC433`. Please also note that the numeric
21 | last part (patch) of github builds always increases and is never the
22 | same for 2 different builds.
23 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/custom_config.ini.example:
--------------------------------------------------------------------------------
1 | ; This file should contain your local modifications to the PlatformIO.ini file.
2 |
3 | [env:myObs]
4 | build_flags =
5 | ${env.build_flags}
6 | ; you can specify a custom config json (see docs/software/firmware/obs_cfg.md)
7 | ; here which will be used for fresh installs based on this firmware
8 | -DCUSTOM_OBS_DEFAULT_CONFIG='"{ obs: [ { displayConfig: 15, offset: [ 30, 30 ], httpPin: \\"12345678\\", wifiSsid: \\"SID\\", wifiPassword: \\"87654321\\" } ] }"'
9 | ; aditional logoutput from 0 (node) over 3 (default info) to 5 debug
10 | -DCORE_DEBUG_LEVEL=3
11 | ; build with development option
12 | ; warning this causes the configuration including the wifi credentials to be sent to serial
13 | -DDEVELOP
14 | ; http lib loglevel
15 | -DHTTPS_LOGLEVEL=3
16 | ; select OBS Variant
17 | -DOBSCLASSIC
18 | ; -DOBSPRO
19 |
20 |
21 | ; === upload_port ===
22 | ; Optional. If not set, PlatformIO will try to autodetect the port.
23 | ; -- macOS --
24 | ; upload_port = /dev/cu.SLAB_USBtoUART
25 | ; -- Windows --
26 | ; upload_port = COM3
27 | ; === build_flags ===
28 | ; build with development option
29 |
--------------------------------------------------------------------------------
/.idea/copyright/openbikesensor_lgpl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/utils/file.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_FILE_H
25 | #define OPENBIKESENSORFIRMWARE_FILE_H
26 |
27 | #include
28 |
29 | class FileUtil {
30 | public:
31 | static bool appendFile(fs::FS &fs, const char * path, const char * message);
32 | };
33 |
34 | #endif //OPENBIKESENSORFIRMWARE_FILE_H
35 |
--------------------------------------------------------------------------------
/src/utils/https.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_HTTPS_H
25 | #define OPENBIKESENSORFIRMWARE_HTTPS_H
26 |
27 | #include
28 | #include
29 |
30 | class Https {
31 | public:
32 | static httpsserver::SSLCert * getCertificate(const std::function& progress = nullptr);
33 | static bool removeCertificate();
34 | static bool existsCertificate();
35 | };
36 |
37 | #endif //OPENBIKESENSORFIRMWARE_HTTPS_H
38 |
--------------------------------------------------------------------------------
/src/utils/file.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "file.h"
25 |
26 | bool FileUtil::appendFile(fs::FS &fs, const char * path, const char * message) {
27 | bool result = false;
28 | log_i("Appending to file: %s", path);
29 |
30 | File file = fs.open(path, FILE_APPEND);
31 | if (!file) {
32 | log_e("Failed to open file for appending");
33 | return false;
34 | }
35 | if (file.print(message)) {
36 | result = true;
37 | } else {
38 | log_e("Append failed");
39 | }
40 | file.close();
41 | return result;
42 | }
43 |
--------------------------------------------------------------------------------
/src/OpenBikeSensorFirmware.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_OPENBIKESENSORFIRMWARE_H
25 | #define OBS_OPENBIKESENSORFIRMWARE_H
26 |
27 | #include
28 | #define CIRCULAR_BUFFER_INT_SAFE
29 | #include
30 |
31 | #include "config.h"
32 | #include "configServer.h"
33 | #include "displays.h"
34 | #include "globals.h"
35 | #include "gps.h"
36 | #include "sensor.h"
37 | #include "pgaSensor.h"
38 | #include "writer.h"
39 |
40 | #include
41 | #include
42 |
43 | #include "bluetooth/BluetoothManager.h"
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/src/Firmware.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 | #ifndef OPENBIKESENSORFIRMWARE_FIRMWARE_H
24 | #define OPENBIKESENSORFIRMWARE_FIRMWARE_H
25 |
26 |
27 | #include
28 |
29 | class Firmware {
30 | public:
31 | explicit Firmware(String userAgent) : mUserAgent(userAgent) {};
32 | void downloadToSd(String url, String filename, bool unsafe);
33 | bool downloadToFlash(String url, std::function progress, bool unsafe);
34 | String getLastMessage();
35 |
36 | static String getFlashAppVersion();
37 | static String checkSdFirmware();
38 | static bool switchToFlashApp();
39 |
40 | private:
41 | String mLastMessage;
42 | String mUserAgent;
43 | static const esp_partition_t *findEspFlashAppPartition();
44 | };
45 |
46 |
47 | #endif //OPENBIKESENSORFIRMWARE_FIRMWARE_H
48 |
--------------------------------------------------------------------------------
/src/uploader.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef UPLOADER_H
25 | #define UPLOADER_H
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | class Uploader {
32 | public:
33 | Uploader(String portalUrl, String userToken);
34 | /* uploads the named file to the portal,
35 | * moves it to uploaded directory and
36 | * returns true if successful, otherwise false */
37 | bool upload(const String& fileName);
38 | String getLastStatusMessage() const;
39 | String getLastLocation() const;
40 |
41 | private:
42 | const String mPortalUrl;
43 | const String mPortalUserToken;
44 | WiFiClientSecure mWiFiClient;
45 | String mLastLocation = "";
46 | String mLastStatusMessage = "NO UPLOAD";
47 |
48 | bool uploadFile(fs::File &file);
49 | };
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/utils/button.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_BUTTON_H
25 | #define OPENBIKESENSORFIRMWARE_BUTTON_H
26 |
27 |
28 | class Button {
29 | public:
30 | explicit Button(int pin);
31 | void handle();
32 | void handle(unsigned long millis);
33 | int read() const;
34 | int getState() const;
35 | bool gotPressed();
36 | unsigned long getCurrentStateMillis() const;
37 | unsigned long getPreviousStateMillis() const;
38 |
39 | private:
40 | static const int DEBOUNCE_DELAY_MS = 50;
41 | const int mPin;
42 | unsigned long mLastRawReadMillis;
43 | int mLastRawState;
44 | int mLastState;
45 | unsigned long mLastStateChangeMillis;
46 | unsigned long mPreviousStateDurationMillis = 0;
47 | int mReleaseEvents = 0;
48 | };
49 |
50 |
51 | #endif //OPENBIKESENSORFIRMWARE_BUTTON_H
52 |
--------------------------------------------------------------------------------
/src/bluetooth/BatteryService.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "BatteryService.h"
25 |
26 | const BLEUUID BatteryService::BATTERY_SERVICE_UUID = BLEUUID((uint16_t)0x180f);
27 | const BLEUUID BatteryService::BATTERY_LEVEL_CHARACTERISTIC_UUID = BLEUUID((uint16_t)0x2a19);
28 |
29 |
30 | void BatteryService::setup(BLEServer *pServer) {
31 | mService = pServer->createService(BATTERY_SERVICE_UUID);
32 |
33 | mService->addCharacteristic(&mBatteryLevelCharacteristic);
34 | mBatteryLevelCharacteristic.setCallbacks(&mBatteryLevelCallback);
35 | }
36 |
37 | bool BatteryService::shouldAdvertise() {
38 | return false;
39 | }
40 |
41 | BLEService* BatteryService::getService() {
42 | return mService;
43 | }
44 |
45 | void BatteryLevelCallback::onRead(BLECharacteristic *pCharacteristic) {
46 | *mValue = mGetLevel();
47 | pCharacteristic->setValue(mValue, 1);
48 | }
--------------------------------------------------------------------------------
/src/bluetooth/DeviceInfoService.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "DeviceInfoService.h"
25 |
26 | const BLEUUID DeviceInfoService::SERVICE_UUID = BLEUUID((uint16_t)0x180a);
27 | const BLEUUID DeviceInfoService::FIRMWARE_VERSION_CHARACTERISTIC_UUID = BLEUUID((uint16_t)0x2a26);
28 | const BLEUUID DeviceInfoService::MANUFACTURER_NAME_CHARACTERISTIC_UUID = BLEUUID((uint16_t)0x2a29);
29 |
30 |
31 | void DeviceInfoService::setup(BLEServer *pServer) {
32 | mService = pServer->createService(SERVICE_UUID);
33 | mService->addCharacteristic(&mFirmwareRevisionCharacteristic);
34 | mFirmwareRevisionCharacteristic.setValue(OBSVersion);
35 | mService->addCharacteristic(&mManufacturerNameCharacteristic);
36 | mManufacturerNameCharacteristic.setValue(std::string("openbikesensor.org"));
37 | }
38 |
39 | bool DeviceInfoService::shouldAdvertise() {
40 | return false;
41 | }
42 |
43 | BLEService* DeviceInfoService::getService() {
44 | return mService;
45 | }
46 |
--------------------------------------------------------------------------------
/src/bluetooth/HeartRateService.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_BLUETOOTH_HEARTRATESERVICE_H
25 | #define OBS_BLUETOOTH_HEARTRATESERVICE_H
26 |
27 | #include "_IBluetoothService.h"
28 |
29 | class HeartRateService : public IBluetoothService {
30 | public:
31 | void setup(BLEServer *pServer) override;
32 | bool shouldAdvertise() override;
33 | BLEService* getService() override;
34 | void newSensorValues(uint32_t millis, uint16_t leftValue, uint16_t rightValue) override;
35 |
36 | private:
37 | BLEService *mService = nullptr;
38 | BLECharacteristic mHeartRateMeasurementCharacteristics
39 | = BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_HEART_RATE_MEAS), BLECharacteristic::PROPERTY_NOTIFY);
40 | BLE2902 mHeartRateMeasurementConfiguration;
41 | unsigned long mCollectionStartTime = 0;
42 | uint16_t mMinimumDistance = MAX_SENSOR_VALUE;
43 | uint8_t mValue[4];
44 |
45 | static const BLEUUID SERVICE_UUID;
46 | };
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/src/fonts/logos.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | const unsigned char BatterieLogo1 [] PROGMEM = {
25 | 0x1C, 0x3E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E
26 | };
27 | const unsigned char BatterieLogo2 [] PROGMEM = {
28 | 0x1C, 0x3E, 0x41, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E
29 | };
30 | const unsigned char BatterieLogo3 [] PROGMEM = {
31 | 0x1C, 0x3E, 0x41, 0x41, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E
32 | };
33 | const unsigned char BatterieLogo4 [] PROGMEM = {
34 | 0x1C, 0x3E, 0x41, 0x41, 0x41, 0x7F, 0x7F, 0x7F, 0x3E
35 | };
36 | const unsigned char BatterieLogo5 [] PROGMEM = {
37 | 0x1C, 0x3E, 0x41, 0x41, 0x41, 0x41, 0x7F, 0x7F, 0x3E
38 | };
39 | const unsigned char BatterieLogo6 [] PROGMEM = {
40 | 0x1C, 0x3E, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7F, 0x3E
41 | };
42 | const unsigned char BatterieLogo7 [] PROGMEM = {
43 | 0x1C, 0x3E, 0x41, 0x41, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E
44 | };
45 |
46 | const unsigned char TempLogo [] PROGMEM = {
47 | 0x10, 0x28, 0x28, 0x28, 0x28, 0x28, 0x44, 0x44, 0x38
48 | };
49 |
--------------------------------------------------------------------------------
/src/configServer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | // Based on https://lastminuteengineers.com/esp32-ota-web-updater-arduino-ide/
25 | // The information provided on the LastMinuteEngineers.com may be used, copied,
26 | // remix, transform, build upon the material and distributed for any purposes
27 | // only if provided appropriate credit to the author and link to the original article.
28 |
29 | #ifndef OBS_CONFIG_SERVER_H
30 | #define OBS_CONFIG_SERVER_H
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | #include "config.h"
41 | #include "globals.h"
42 | #include "gps.h"
43 |
44 | // DNS server
45 | //const byte DNS_PORT = 53;
46 | //DNSServer dnsServer;
47 |
48 | void startServer(ObsConfig *pConfig);
49 | bool configServerWasConnectedViaHttp();
50 | void uploadTracks(httpsserver::HTTPResponse *res = nullptr);
51 | void configServerHandle();
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/utils/obsutils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_OBSUTILS_H
25 | #define OPENBIKESENSORFIRMWARE_OBSUTILS_H
26 |
27 | #include
28 |
29 | /**
30 | * Class for internal - static only methods.
31 | */
32 | class ObsUtils {
33 | public:
34 | static String createTrackUuid();
35 | static String sha256ToString(byte *sha256);
36 | /* Strips technical details like extension or '/' from the file name. */
37 | static String stripCsvFileName(const String &fileName);
38 | static String encodeForXmlAttribute(const String & text);
39 | static String encodeForXmlText(const String &text);
40 | static String encodeForCsvField(const String &field);
41 | static String encodeForUrl(const String &url);
42 | static String toScaledByteString(uint64_t size);
43 | static void logHexDump(const uint8_t *buffer, uint16_t length);
44 | static String to3DigitString(uint32_t value);
45 |
46 | };
47 |
48 |
49 | #endif //OPENBIKESENSORFIRMWARE_OBSUTILS_H
50 |
--------------------------------------------------------------------------------
/src/bluetooth/DeviceInfoService.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_BLUETOOTH_DEVICEINFOSERVICE_H
25 | #define OBS_BLUETOOTH_DEVICEINFOSERVICE_H
26 |
27 | #include "_IBluetoothService.h"
28 |
29 | /*
30 | * See https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=244369 for spec
31 | */
32 | class DeviceInfoService : public IBluetoothService {
33 | public:
34 | void setup(BLEServer *pServer) override;
35 | bool shouldAdvertise() override;
36 | BLEService* getService() override;
37 |
38 | private:
39 | BLEService *mService = nullptr;
40 | BLECharacteristic mFirmwareRevisionCharacteristic
41 | = BLECharacteristic(FIRMWARE_VERSION_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
42 | BLECharacteristic mManufacturerNameCharacteristic
43 | = BLECharacteristic(MANUFACTURER_NAME_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
44 |
45 | static const BLEUUID SERVICE_UUID;
46 | static const BLEUUID FIRMWARE_VERSION_CHARACTERISTIC_UUID;
47 | static const BLEUUID MANUFACTURER_NAME_CHARACTERISTIC_UUID;
48 | };
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '37 23 * * 1'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | container:
28 | # could use a container with sq tools already installed
29 | image: infinitecoding/platformio-for-ci:latest
30 |
31 | strategy:
32 | fail-fast: false
33 | matrix:
34 | language: [ 'cpp' ]
35 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
36 | # Learn more:
37 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v4
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v3
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
52 |
53 | - name: Build firmware
54 | run: |
55 | platformio ci --build-dir="./bin" --keep-build-dir --project-conf=platformio.ini ./src/
56 |
57 | - name: Perform CodeQL Analysis
58 | uses: github/codeql-action/analyze@v3
59 |
--------------------------------------------------------------------------------
/src/globals.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_GLOBALS_H
25 | #define OBS_GLOBALS_H
26 |
27 | #include
28 |
29 | // Forward declare classes to build (because there is a cyclic dependency between sensor.h and displays.h)
30 | class DisplayDevice;
31 | class HCSR04SensorManager;
32 |
33 |
34 | #include "utils/obsutils.h"
35 | #include "config.h"
36 | #include "displays.h"
37 | #include "sensor.h"
38 | #include "pgaSensor.h"
39 | #include "VoltageMeter.h"
40 | #include "utils/button.h"
41 | #include "variant.h"
42 |
43 | // This file should contain declarations of all variables that will be used globally.
44 | // The variables don't have to be set here, but need to be declared.
45 |
46 | // Version
47 | extern const char *OBSVersion;
48 |
49 | // PINs
50 | extern const int PUSHBUTTON_PIN;
51 |
52 | extern int confirmedMeasurements;
53 | extern int numButtonReleased;
54 |
55 | extern Config config;
56 |
57 |
58 | extern DisplayDevice* obsDisplay;
59 |
60 | #ifdef OBSPRO
61 | extern PGASensorManager *sensorManager;
62 | #endif
63 | #ifdef OBSCLASSIC
64 | extern HCSR04SensorManager* sensorManager;
65 | #endif
66 |
67 | extern VoltageMeter* voltageMeter;
68 |
69 | extern Button button;
70 |
71 | class Gps;
72 | extern Gps gps;
73 |
74 | extern const uint8_t LEFT_SENSOR_ID;
75 | extern const uint8_t RIGHT_SENSOR_ID;
76 |
77 | #endif
78 |
--------------------------------------------------------------------------------
/src/utils/median.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_MEDIAN_H
25 | #define OPENBIKESENSORFIRMWARE_MEDIAN_H
26 |
27 | #include
28 |
29 | template class Median {
30 |
31 | public:
32 | /* Simple implementation, size must be odd! */
33 | Median(size_t size, T initialValue):
34 | size{size},
35 | mid{size/2},
36 | data{new T[size]},
37 | temp{new T[size]},
38 | pos{0} {
39 | for(size_t i = 0; i < size; i++) {
40 | data[i] = initialValue;
41 | }
42 | };
43 | ~Median() {
44 | log_i("Will free Median(%d/%d) -> 0x%lx", size, mid, data);
45 | delete[] data;
46 | delete[] temp;
47 | };
48 | void addValue(T value) {
49 | sorted = false;
50 | data[pos++] = value;
51 | if (pos >= size) {
52 | pos = 0;
53 | }
54 | };
55 | T median() {
56 | if (!sorted) {
57 | memcpy(temp, data, sizeof(T) * size); // std:copy needs to much mem
58 | std::sort(&temp[0], &temp[size]);
59 | sorted = true;
60 | }
61 | return temp[mid];
62 | };
63 |
64 | private:
65 | const size_t size;
66 | const size_t mid;
67 | T *data;
68 | T *temp;
69 | size_t pos = 0;
70 | boolean sorted = false;
71 | };
72 |
73 | #endif //OPENBIKESENSORFIRMWARE_MEDIAN_H
74 |
--------------------------------------------------------------------------------
/src/utils/alpdata.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_ALPDATA_H
25 | #define OPENBIKESENSORFIRMWARE_ALPDATA_H
26 |
27 | #include
28 | #include "displays.h"
29 |
30 | static const char *const LAST_MODIFIED_HEADER_FILE_NAME = "/current_14d.hdr";
31 |
32 | static const char *const ALP_DATA_FILE_NAME = "/current_14d.alp";
33 | static const char *const ALP_NEW_DATA_FILE_NAME = "/current_14d.new";
34 | static const char *const AID_INI_DATA_FILE_NAME = "/aid_ini.ubx";
35 |
36 | static const int32_t ALP_DATA_MIN_FILE_SIZE = 60000; // We have seen 71k ALP files - so lets hope 60k is safe
37 |
38 | static const char *const ALP_DOWNLOAD_URL = "https://alp.u-blox.com/current_14d.alp";
39 |
40 | class AlpData {
41 | public:
42 | static void update(DisplayDevice *display);
43 | static bool available();
44 | static void saveMessage(const uint8_t *data, size_t size);
45 | static size_t loadMessage(uint8_t *data, size_t size);
46 |
47 | uint16_t fill(uint8_t *data, size_t ofs, uint16_t dataSize);
48 | void save(const uint8_t *data, size_t offset, int length);
49 |
50 | private:
51 | static void saveLastModified(const String &header);
52 | static String loadLastModified();
53 | static void displayHttpClientError(DisplayDevice *display, int httpError);
54 | File mAlpDataFile;
55 |
56 | };
57 |
58 |
59 | #endif //OPENBIKESENSORFIRMWARE_ALPDATA_H
60 |
--------------------------------------------------------------------------------
/src/VoltageMeter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_VOLTAGEMETER_H
25 | #define OPENBIKESENSORFIRMWARE_VOLTAGEMETER_H
26 |
27 | #include
28 | #include
29 |
30 | class VoltageMeter {
31 | public:
32 | explicit VoltageMeter(
33 | uint8_t batteryPin = 34,
34 | adc1_channel_t channel = ADC1_CHANNEL_6);
35 | /* Returns the (smoothed) value in Volts. */
36 | double read();
37 | int8_t readPercentage();
38 | bool hasReadings();
39 | bool isWarningLevel();
40 |
41 | private:
42 | /* This one is typically NOT used, our ESP32 dos have
43 | * Vref stored in the eFuse which takes priority. */
44 | static const uint16_t REF_VOLTAGE_MILLI_VOLT = 1100;
45 | static const int16_t MINIMUM_SAMPLES = 64;
46 | static const int16_t SAMPLES_DIVIDE = 128;
47 |
48 | /* Below this value a warning will be printed during startup. */
49 | constexpr static const double BATTERY_WARNING_LEVEL = 3.47;
50 | /* Below this value it is assumed there is no voltage reading at all. */
51 | constexpr static const double BATTERY_NO_READ_LEVEL = 3.00;
52 |
53 | const uint8_t mBatteryPin;
54 | const adc1_channel_t mBatteryAdcChannel;
55 | esp_adc_cal_characteristics_t adc_chars;
56 | int16_t lastSmoothedReading;
57 | int readSmoothed();
58 | int readRaw() const;
59 | };
60 |
61 |
62 | #endif //OPENBIKESENSORFIRMWARE_VOLTAGEMETER_H
63 |
--------------------------------------------------------------------------------
/src/bluetooth/BatteryService.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_BATTERYSERVICE_H
25 | #define OPENBIKESENSORFIRMWARE_BATTERYSERVICE_H
26 |
27 | #include "_IBluetoothService.h"
28 | #include
29 |
30 | class BatteryLevelCallback : public BLECharacteristicCallbacks {
31 | public:
32 | explicit BatteryLevelCallback(uint8_t *value, std::function getLevel) :
33 | mValue(value), mGetLevel(getLevel) {};
34 |
35 | void onRead(BLECharacteristic *pCharacteristic) override;
36 |
37 | private:
38 | uint8_t *mValue;
39 | const std::function mGetLevel;
40 | };
41 |
42 | class BatteryService : public IBluetoothService {
43 | public:
44 | explicit BatteryService(std::function getLevel) : mBatteryLevelCallback(&mBatteryLevelValue, getLevel) { };
45 | void setup(BLEServer *pServer) override;
46 | bool shouldAdvertise() override;
47 | BLEService* getService() override;
48 |
49 | private:
50 | BLEService *mService = nullptr;
51 | BLECharacteristic mBatteryLevelCharacteristic = BLECharacteristic(
52 | BATTERY_LEVEL_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
53 |
54 | uint8_t mBatteryLevelValue = 42;
55 | BatteryLevelCallback mBatteryLevelCallback;
56 |
57 | static const BLEUUID BATTERY_SERVICE_UUID;
58 | static const BLEUUID BATTERY_LEVEL_CHARACTERISTIC_UUID;
59 | };
60 |
61 |
62 | #endif //OPENBIKESENSORFIRMWARE_BATTERYSERVICE_H
63 |
--------------------------------------------------------------------------------
/src/utils/timeutils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_TIMEUTILS_H
25 | #define OPENBIKESENSORFIRMWARE_TIMEUTILS_H
26 |
27 | #include
28 |
29 | class TimeUtils {
30 | public:
31 | static const time_t PAST_TIME;
32 | static String dateTimeToString(time_t timeIn = 0);
33 | static String timeToString(time_t theTime =0);
34 | static String dateTimeToHttpHeaderString(time_t theTime);
35 | static void setClockByNtp(const char *ntpServer = nullptr);
36 | static void setClockByNtpAndWait(const char *ntpServer = nullptr, uint32_t timeout = 3 * 60 * 1000);
37 | static void setClockByGps(uint32_t iTow, int32_t fTow, int16_t week, int8_t leapS = 0);
38 | static bool systemTimeIsSet();
39 | static int16_t getLeapSecondsGps(time_t gps);
40 | static int16_t getLeapSecondsUtc(time_t gps);
41 | static time_t gpsDayToTime(uint16_t week, uint16_t dayOfWeek);
42 | static time_t toTime(uint16_t week, uint32_t weekTime);
43 | static uint32_t utcTimeToTimeOfWeek(time_t t);
44 | static uint16_t utcTimeToWeekNumber(time_t t);
45 |
46 | private:
47 | static const char *WEEK_DAYS[7];
48 | static const char *MONTHS[12];
49 | static const uint32_t GPS_EPOCH_OFFSET;
50 | static const uint32_t SECONDS_PER_DAY;
51 | static const uint32_t SECONDS_PER_WEEK;
52 | static const char *weekDayToString(uint8_t wDay);
53 | static const char *monthToString(uint8_t mon);
54 | };
55 |
56 |
57 | #endif //OPENBIKESENSORFIRMWARE_TIMEUTILS_H
58 |
--------------------------------------------------------------------------------
/src/utils/streams.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_STREAMS_H
25 | #define OPENBIKESENSORFIRMWARE_STREAMS_H
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 |
33 | class StringStream : public Stream {
34 | public:
35 | explicit StringStream(String str);
36 |
37 | int available() override;
38 |
39 | int read() override;
40 |
41 | int peek() override;
42 |
43 | void flush() override;
44 |
45 | size_t write(uint8_t) override;
46 |
47 | size_t readBytes(char *buffer, size_t length) override;
48 |
49 | private:
50 | String string;
51 | size_t pos = 0;
52 | };
53 |
54 | static StringStream EMPTY_STREAM("");
55 |
56 | class StreamOfStreams : public Stream {
57 | public:
58 | void push(Stream *addedStream);
59 |
60 | int available() override;
61 |
62 | int read() override;
63 |
64 | int peek() override;
65 |
66 | void flush() override;
67 |
68 | size_t write(uint8_t) override;
69 |
70 | void setProgressListener(std::function);
71 |
72 | size_t readBytes(char *buffer, size_t length) override;
73 |
74 | private:
75 | Stream *current = nullptr;
76 | std::vector streams;
77 | size_t pos = 0;
78 | std::function progressListener = nullptr;
79 | size_t overallBytePos = 0;
80 |
81 |
82 | Stream *getCurrent();
83 |
84 | Stream *getNext();
85 | };
86 |
87 |
88 | #endif //OPENBIKESENSORFIRMWARE_STREAMS_H
89 |
--------------------------------------------------------------------------------
/src/utils/button.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "button.h"
25 | #include "esp32-hal-gpio.h"
26 | #include "variant.h"
27 |
28 | Button::Button(int pin) : mPin(pin) {
29 | pinMode(pin, INPUT);
30 | mLastStateChangeMillis = mLastRawReadMillis = millis();
31 | mLastState = mLastRawState = read();
32 | }
33 |
34 | void Button::handle() {
35 | handle(millis());
36 | }
37 |
38 | void Button::handle(unsigned long millis) {
39 | const int state = read();
40 |
41 | if (state != mLastRawState) {
42 | mLastRawReadMillis = millis;
43 | mLastRawState = state;
44 | }
45 |
46 | if (state != mLastState && millis - mLastRawReadMillis > DEBOUNCE_DELAY_MS) {
47 | mLastState = state;
48 | mPreviousStateDurationMillis = millis - mLastStateChangeMillis;
49 | mLastStateChangeMillis = millis;
50 | if (state == LOW) {
51 | // can distinguish long / short here if needed
52 | mReleaseEvents++;
53 | }
54 | }
55 | }
56 |
57 | bool Button::gotPressed() {
58 | if (mReleaseEvents > 0) {
59 | mReleaseEvents = 0;
60 | return true;
61 | } else {
62 | return false;
63 | }
64 | }
65 |
66 | int Button::read() const {
67 | // not debounced
68 | #ifdef OBSPRO
69 | return !digitalRead(mPin);
70 | #else
71 | return digitalRead(mPin);
72 | #endif
73 | }
74 |
75 | int Button::getState() const {
76 | // debounced, needs handle to be called
77 | return mLastState;
78 | }
79 |
80 | unsigned long Button::getCurrentStateMillis() const {
81 | return millis() - mLastStateChangeMillis;
82 | }
83 |
84 | unsigned long Button::getPreviousStateMillis() const {
85 | return mPreviousStateDurationMillis;
86 | }
87 |
--------------------------------------------------------------------------------
/src/bluetooth/HeartRateService.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "HeartRateService.h"
25 |
26 | const unsigned long measurementInterval = 500;
27 |
28 | const BLEUUID HeartRateService::SERVICE_UUID = BLEUUID((uint16_t)ESP_GATT_UUID_HEART_RATE_SVC);
29 |
30 | void HeartRateService::setup(BLEServer *pServer) {
31 | mService = pServer->createService(SERVICE_UUID); // Keep the defaults!!, 5);
32 | mService->addCharacteristic(&mHeartRateMeasurementCharacteristics);
33 | mHeartRateMeasurementCharacteristics.addDescriptor(&mHeartRateMeasurementConfiguration);
34 | mValue[0] = mValue[1] = mValue[2] = 0;
35 | mHeartRateMeasurementCharacteristics.setValue(mValue, 2);
36 |
37 | mCollectionStartTime = millis();
38 | }
39 |
40 | bool HeartRateService::shouldAdvertise() {
41 | return true;
42 | }
43 |
44 | BLEService* HeartRateService::getService() {
45 | return mService;
46 | }
47 |
48 | void HeartRateService::newSensorValues(
49 | const uint32_t millis, const uint16_t leftValue, const uint16_t rightValue) {
50 | if (leftValue < mMinimumDistance) {
51 | mMinimumDistance = leftValue;
52 | }
53 | if ((millis - mCollectionStartTime) < measurementInterval) {
54 | return;
55 | }
56 |
57 | if (mHeartRateMeasurementConfiguration.getNotifications()) {
58 | mValue[0] = mMinimumDistance <= UINT8_MAX ? 0 : 1; // 8/16 bit data no other flags set;
59 | mValue[1] = mMinimumDistance & 0xFFu;
60 | mValue[2] = mMinimumDistance >> 8u;
61 | mHeartRateMeasurementCharacteristics.setValue(mValue, mMinimumDistance <= UINT8_MAX ? 2 : 3);
62 | mHeartRateMeasurementCharacteristics.notify();
63 | }
64 |
65 | // Reset values
66 | mMinimumDistance = MAX_SENSOR_VALUE;
67 | mCollectionStartTime = millis;
68 | }
69 |
--------------------------------------------------------------------------------
/src/variant.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2023 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef VARIANT_H
25 | #define VARIANT_H
26 |
27 |
28 | // Use custom_config.ini to set the needed variant!
29 | // If set, the firmware is build for the OBSPro hardware variant
30 | // The main differences are:
31 | // - The button is inverted
32 | // - The button is also responsible for soft-power-off
33 | // - The display is a JHD12864-G156BT which is SPI based
34 | // - The ultrasonic sensors are PGA460 based
35 | //#define OBSPRO
36 |
37 | // If set, the firmware is build for the OBSClassic
38 | //#define OBSCLASSIC
39 |
40 | // Settings specific to OBSPro
41 | #ifdef OBSPRO
42 | #define LCD_CS_PIN 12
43 | #define LCD_DC_PIN 27
44 | #define LCD_RESET_PIN 4
45 |
46 | #define SENSOR1_SCK_PIN 25
47 | #define SENSOR1_MOSI_PIN 33
48 | #define SENSOR1_MISO_PIN 32
49 |
50 | #define SENSOR2_SCK_PIN 14
51 | #define SENSOR2_MOSI_PIN 15
52 | #define SENSOR2_MISO_PIN 21
53 | #define UBX_M10
54 |
55 | #define POWER_KEEP_ALIVE_INTERVAL_MS 5000UL
56 | #endif
57 |
58 | // Settings specific to OBSClassic
59 | #if OBSCLASSIC
60 | #define UBX_M6
61 | #endif
62 |
63 |
64 | // General settings
65 | #define NUMBER_OF_TOF_SENSORS 2
66 | #define MAX_SENSOR_VALUE 999
67 | #define MAX_NUMBER_MEASUREMENTS_PER_INTERVAL 30 // is 1000/SENSOR_QUIET_PERIOD_AFTER_START_MICRO_SEC/2
68 | #define MEDIAN_DISTANCE_MEASURES 3
69 |
70 | #define MIN_DISTANCE_MEASURED_CM 2
71 | #ifdef OBSPRO
72 | #define MAX_DISTANCE_MEASURED_CM 600
73 | #else
74 | #define MAX_DISTANCE_MEASURED_CM 320 // candidate to check I could not get good readings above 300
75 | #endif
76 |
77 | #define MICRO_SEC_TO_CM_DIVIDER 58 // sound speed 340M/S, 2 times back and forward
78 |
79 | #define MIN_DURATION_MICRO_SEC (MIN_DISTANCE_MEASURED_CM * MICRO_SEC_TO_CM_DIVIDER)
80 | #define MAX_DURATION_MICRO_SEC (MAX_DISTANCE_MEASURED_CM * MICRO_SEC_TO_CM_DIVIDER)
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/src/writer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_WRITER_H
25 | #define OBS_WRITER_H
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include "gps.h"
32 | #include "globals.h"
33 |
34 |
35 | struct DataSet {
36 | time_t time;
37 | uint32_t millis;
38 | String comment;
39 | GpsRecord gpsRecord;
40 | double batteryLevel;
41 | std::vector sensorValues;
42 | std::vector confirmedDistances;
43 | std::vector confirmedDistancesIndex;
44 | uint16_t confirmed = 0;
45 | String marked;
46 | bool invalidMeasurement = false;
47 | bool isInsidePrivacyArea = false;
48 | uint8_t factor = MICRO_SEC_TO_CM_DIVIDER;
49 | uint8_t measurements;
50 |
51 | uint16_t position = 0; // fixme: num sensors?
52 | uint16_t startOffsetMilliseconds[MAX_NUMBER_MEASUREMENTS_PER_INTERVAL + 1];
53 | int32_t readDurationsLeftInMicroseconds[MAX_NUMBER_MEASUREMENTS_PER_INTERVAL + 1];
54 | int32_t readDurationsRightInMicroseconds[MAX_NUMBER_MEASUREMENTS_PER_INTERVAL + 1];
55 | };
56 |
57 | class FileWriter {
58 | public:
59 | FileWriter() = default;;
60 | explicit FileWriter(String ext) :
61 | mFileExtension(std::move(ext)) {};
62 | virtual ~FileWriter() = default;
63 | void setFileName();
64 | virtual bool writeHeader(String trackId) = 0;
65 | virtual bool append(DataSet &) = 0;
66 | bool appendString(const String &s);
67 | bool flush();
68 | unsigned long getWriteTimeMillis() const;
69 |
70 | protected:
71 | uint16_t getBufferLength() const;
72 |
73 | private:
74 | static void storeTrackNumber(int trackNumber);
75 | static int getTrackNumber();
76 | void correctFilename();
77 | String mBuffer;
78 | String mFileExtension;
79 | String mFileName;
80 | const unsigned long mStartedMillis = millis();
81 | bool mFinalFileName = false;
82 | unsigned long mWriteTimeMillis = 0;
83 |
84 | };
85 |
86 | class CSVFileWriter : public FileWriter {
87 | public:
88 | CSVFileWriter() : FileWriter(EXTENSION) {}
89 | ~CSVFileWriter() override = default;
90 | bool writeHeader(String trackId) override;
91 | bool append(DataSet&) override;
92 | static const String EXTENSION;
93 | };
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/src/bluetooth/ObsService.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_OBSSERVICE_H
25 | #define OPENBIKESENSORFIRMWARE_OBSSERVICE_H
26 |
27 | #include "_IBluetoothService.h"
28 |
29 |
30 | class ObsTimeServiceCallback : public BLECharacteristicCallbacks {
31 | public:
32 | void onRead(BLECharacteristic *pCharacteristic) override;
33 | };
34 |
35 |
36 | class ObsService : public IBluetoothService {
37 | public:
38 | ObsService(uint16_t leftOffset, uint16_t rightOffset, const String &trackId);
39 | void setup(BLEServer *pServer) override;
40 | bool shouldAdvertise() override;
41 | BLEService* getService() override;
42 | void newSensorValues(uint32_t millis, uint16_t leftValue, uint16_t rightValue) override;
43 | void newPassEvent(uint32_t millis, uint16_t leftValue, uint16_t rightValue) override;
44 |
45 | private:
46 | BLEService *mService = nullptr;
47 |
48 | BLECharacteristic mTimeCharacteristic
49 | = BLECharacteristic(OBS_TIME_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
50 | ObsTimeServiceCallback mTimeCharacteristicsCallback;
51 |
52 | BLECharacteristic mDistanceCharacteristic
53 | = BLECharacteristic(OBS_DISTANCE_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY);
54 | BLE2902 mDistanceConfiguration;
55 |
56 | BLECharacteristic mButtonCharacteristic
57 | = BLECharacteristic(OBS_BUTTON_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY);
58 |
59 | BLECharacteristic mOffsetCharacteristic
60 | = BLECharacteristic(OBS_OFFSET_CHARACTERISTIC_UUID,BLECharacteristic::PROPERTY_READ);
61 |
62 | BLECharacteristic mTrackIdCharacteristic
63 | = BLECharacteristic(OBS_TRACK_ID_CHARACTERISTIC_UUID,BLECharacteristic::PROPERTY_READ);
64 |
65 | static const BLEUUID OBS_SERVICE_UUID;
66 | static const BLEUUID OBS_TIME_CHARACTERISTIC_UUID;
67 | static const BLEUUID OBS_DISTANCE_CHARACTERISTIC_UUID;
68 | static const BLEUUID OBS_BUTTON_CHARACTERISTIC_UUID;
69 | static const BLEUUID OBS_OFFSET_CHARACTERISTIC_UUID;
70 | static const BLEUUID OBS_TRACK_ID_CHARACTERISTIC_UUID;
71 | static void sendEventData(BLECharacteristic *characteristic,
72 | uint32_t millis, uint16_t leftValue, uint16_t rightValue);
73 |
74 | };
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/bluetooth/_IBluetoothService.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_BLUETOOTH_IBLUETOOTHSERVICE_H
25 | #define OBS_BLUETOOTH_IBLUETOOTHSERVICE_H
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include "globals.h"
33 |
34 | /**
35 | * This class interface defines how a bluetooth service should work.
36 | * Any child class should override every public method.
37 | */
38 | class IBluetoothService {
39 | public:
40 | /**
41 | * This method initializes the class and expects the instance to create its
42 | * own BLEService and its characteristics.
43 | * @param pServer pointer to the bluetooth server
44 | */
45 | virtual void setup(BLEServer *pServer) = 0;
46 |
47 | /**
48 | * Whether this bluetooth service should be advertised or not.
49 | */
50 | virtual bool shouldAdvertise() = 0;
51 |
52 | /**
53 | * Gets the only BLEService that was created in setup().
54 | */
55 | virtual BLEService* getService() = 0;
56 |
57 | /**
58 | * Processes new sensor values from both sides.
59 | * @param millis sender millis counter at the time of measurement of the left value
60 | * @param leftValue sensor value of the left side (MAX_SENSOR_VALUE for no reading)
61 | * @param rightValues sensor value of the right side (MAX_SENSOR_VALUE for no reading)
62 | */
63 | virtual void newSensorValues(uint32_t millis, uint16_t leftValue, uint16_t rightValue) {
64 | // empty default implementation
65 | }
66 |
67 | /**
68 | * Processes new confirmed overtake event.
69 | * @param millis sender millis counter at the time of measurement of the left value
70 | * @param leftValue sensor value of the left side (MAX_SENSOR_VALUE for no reading)
71 | * @param rightValues sensor value of the right side (MAX_SENSOR_VALUE for no reading)
72 | */
73 | virtual void newPassEvent(uint32_t millis, uint16_t leftValue, uint16_t rightValue) {
74 | // empty default implementation
75 | }
76 |
77 | protected:
78 | static String valueAsString(uint16_t value) {
79 | if (value == MAX_SENSOR_VALUE || value == 0) {
80 | return String("");
81 | } else{
82 | return String(value);
83 | }
84 | }
85 | };
86 |
87 | #endif
88 |
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; Copyright (C) 2019-2021 OpenBikeSensor Contributors
2 | ; Contact: https://openbikesensor.org
3 | ;
4 | ; This file is part of the OpenBikeSensor firmware.
5 | ;
6 | ; The OpenBikeSensor firmware is free software: you can
7 | ; redistribute it and/or modify it under the terms of the GNU
8 | ; Lesser General Public License as published by the Free Software
9 | ; Foundation, either version 3 of the License, or (at your option)
10 | ; any later version.
11 | ;
12 | ; OpenBikeSensor firmware is distributed in the hope that
13 | ; it will be useful, but WITHOUT ANY WARRANTY; without even the
14 | ; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 | ; PURPOSE. See the GNU Lesser General Public License for more
16 | ; details.
17 | ;
18 | ; You should have received a copy of the GNU Lesser General Public
19 | ; License along with the OpenBikeSensor firmware. If not,
20 | ; see .
21 |
22 | ; PlatformIO Project Configuration File
23 | ;
24 | ; Build options: build flags, source filter
25 | ; Upload options: custom upload port, speed and extra flags
26 | ; Library options: dependencies, extra library storages
27 | ; Advanced options: extra scripting
28 | ;
29 | ; Please visit documentation for the other options and examples
30 | ; https://docs.platformio.org/page/projectconf.html
31 |
32 | ; If you need to set some configurations differently for your local setup, copy
33 | ; the 'custom_config.ini.example' to 'custom_config.ini' and put your changes there.
34 | ; This new file will be ignored by git and therefore won't be overwritten at some point.
35 |
36 | [platformio]
37 | src_dir = src
38 | extra_configs = custom_config.ini
39 |
40 | [env]
41 | platform = espressif32 @ 6.9.0
42 | board = esp32dev
43 | framework = arduino
44 | monitor_speed = 115200
45 | ; This upload speed is the highest I can get, but I do get reliable uploads
46 | ; with it. If uploads fail for you, comment out the following line:
47 | upload_speed = 921600
48 | board_build.partitions = src/sd-partition-table.csv
49 | board_build.embed_txtfiles = src/truststore/x509_crt_bundle
50 | lib_deps =
51 | adafruit/Adafruit BusIO @ ^1.13.1
52 | ; https://arduinojson.org/v6/api/
53 | bblanchon/ArduinoJson @ ^6.21.5
54 | rlogiacco/CircularBuffer @ ^1.4.0
55 | ; olikraus/U8g2 @ ^2.35.9
56 | https://codeberg.org/j000bs/U8g2_Arduino.git#jhd-fix
57 | ; replaced by U8g2 thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays @ ^4.5.0
58 | adafruit/Adafruit BMP280 Library@^2.6.8
59 | pololu/VL53L0X@^1.3.1
60 | ; https://github.com/fhessel/esp32_https_server
61 | https://github.com/amandel/esp32_https_server.git#hotfix/openbikesensor
62 | ; TODO: https://github.com/jasenk2/esp32_https_server.git#esp_tls
63 | ; esp32_https_server@
64 | build_flags =
65 | -DCORE_DEBUG_LEVEL=3
66 | -DHTTPS_LOGLEVEL=3
67 | -DHTTPS_REQUEST_MAX_REQUEST_LENGTH=1024
68 | ; reduce probability of https://github.com/fhessel/esp32_https_server/pull/123
69 | -DHTTPS_CONNECTION_DATA_CHUNK_SIZE=1024
70 | ; build number "-dev" will be replaced in github action
71 | -DBUILD_NUMBER=\"-dev\"
72 |
73 | [env:obs]
74 | build_flags =
75 | ${env.build_flags}
76 | -DOBSCLASSIC
77 |
78 | [env:obspro]
79 | build_flags =
80 | ${env.build_flags}
81 | -DOBSPRO
82 |
--------------------------------------------------------------------------------
/src/utils/multipart.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_MULTIPART_H
25 | #define OPENBIKESENSORFIRMWARE_MULTIPART_H
26 |
27 | #include
28 | #include
29 | #include "streams.h"
30 |
31 | class MultipartData {
32 | public:
33 | virtual String getHeaders() = 0;
34 |
35 | virtual Stream *asStream() = 0;
36 |
37 | virtual size_t length() = 0;
38 |
39 | explicit MultipartData(String name, String contentType = "");
40 |
41 | protected:
42 | String getBaseHeaders(const String& fileName = "");
43 |
44 | String name;
45 | String contentType;
46 | };
47 |
48 | class MultipartDataString : public MultipartData {
49 | public:
50 |
51 | MultipartDataString(String name, const String& content, String contentType = "");
52 |
53 | String getHeaders() override;
54 |
55 | Stream *asStream() override;
56 |
57 | size_t length() override;
58 |
59 | private:
60 | String content;
61 | StringStream contentStream;
62 | };
63 |
64 | class MultipartDataStream : public MultipartData {
65 | public:
66 | String getHeaders() override;
67 |
68 | Stream *asStream() override;
69 |
70 | size_t length() override;
71 |
72 | MultipartDataStream(String name, String fileName, File *content, String contentType = "");
73 |
74 | private:
75 | String fileName;
76 | File *content;
77 | };
78 |
79 |
80 | class MultipartStream : public Stream {
81 | public:
82 | explicit MultipartStream(HTTPClient *client);
83 |
84 | ~MultipartStream() override;
85 |
86 | size_t predictSize() const;
87 |
88 | void add(MultipartData &newData);
89 |
90 | // API is bast - client must make sure to call last after the last add
91 | void last();
92 |
93 | int available() override;
94 |
95 | int read() override;
96 |
97 | int peek() override;
98 |
99 | void flush() override;
100 |
101 | size_t write(uint8_t) override;
102 |
103 | size_t readBytes(char *buffer, size_t length) override;
104 |
105 | void setProgressListener(std::function);
106 |
107 | private:
108 | HTTPClient *httpClient;
109 | StreamOfStreams streams;
110 | std::vector myStreams;
111 | String boundary;
112 | size_t length = 0;
113 | };
114 |
115 | #endif //OPENBIKESENSORFIRMWARE_MULTIPART_H
116 |
--------------------------------------------------------------------------------
/src/gpsrecord.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_GPSRECORD_H
25 | #define OPENBIKESENSORFIRMWARE_GPSRECORD_H
26 |
27 |
28 | #include
29 | #include
30 |
31 | class Gps;
32 |
33 | class GpsRecord {
34 | enum GPS_FIX : uint8_t {
35 | NO_FIX = 0,
36 | DEAD_RECKONING_ONLY = 1,
37 | FIX_2D = 2,
38 | FIX_3D = 3,
39 | GPS_AND_DEAD_RECKONING = 4,
40 | TIME_ONLY = 5,
41 | };
42 |
43 |
44 |
45 | friend Gps;
46 | public:
47 | String getAltitudeMetersString() const;
48 | String getCourseString() const;
49 | String getSpeedKmHString() const;
50 | String getHdopString() const;
51 | String getLatString() const;
52 | String getLongString() const;
53 | bool hasValidFix() const;
54 | double getLatitude() const;
55 | double getLongitude() const;
56 | uint8_t getSatellitesUsed() const;
57 | uint8_t getFixStatusFlags() const;
58 | GPS_FIX getFixStatus() const;
59 | uint32_t getTow() const;
60 | uint32_t getWeek() const;
61 | uint32_t getCreatedAtMillisTicks() const;
62 |
63 | protected:
64 | /* Clear all collected data */
65 | void reset(uint32_t tow, uint32_t gpsWeek, uint32_t createdAtMillisTicks);
66 |
67 | /* Store tow and related date time data. */
68 | void setWeek(uint32_t gpsWeek);
69 |
70 | void setPosition(int32_t lon, int32_t lat, int32_t height);
71 |
72 | void setVelocity(uint32_t speedOverGround, int32_t heading);
73 |
74 | void setInfo(uint8_t satellitesInUse, GPS_FIX gpsFix, uint8_t flags);
75 |
76 | void setHdop(uint16_t hDop);
77 |
78 | bool isAllSet() const;
79 |
80 | private:
81 | /* Just the GPS Millisecond time of Week of the record, to be able to
82 | * merge records together.
83 | */
84 | uint32_t mCollectTow = 0;
85 | uint32_t mCollectWeek = 0;
86 | /* deg, scale 1e-7 */
87 | int32_t mLongitude;
88 | /* deg, scale 1e-7 */
89 | int32_t mLatitude;
90 | int mSpeed; // * 100?
91 | int mCourseOverGround; // * 100
92 | int mHdop; // * 100
93 | /* millimeter */
94 | int32_t mHeight; // * 10?
95 | uint8_t mSatellitesUsed;
96 | GPS_FIX mFixStatus; //
97 | uint8_t mFixStatusFlags;
98 | bool mPositionSet = false;
99 | bool mVelocitySet = false;
100 | bool mInfoSet = false;
101 | bool mHdopSet = false;
102 | uint32_t mCreatedAtMillisTicks;
103 | static const int32_t pow10[10];
104 | static String toScaledString(int32_t value, uint16_t scale);
105 | };
106 |
107 |
108 | #endif //OPENBIKESENSORFIRMWARE_GPSRECORD_H
109 |
--------------------------------------------------------------------------------
/src/bluetooth/BluetoothManager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_BLUETOOTH_BLUETOOTHMANAGER_H
25 | #define OBS_BLUETOOTH_BLUETOOTHMANAGER_H
26 |
27 | #include
28 | #include
29 |
30 | #include "_IBluetoothService.h"
31 | #include "DeviceInfoService.h"
32 | #include "HeartRateService.h"
33 | #include "BatteryService.h"
34 | #include "ObsService.h"
35 |
36 | class BluetoothManager: public BLEServerCallbacks {
37 | public:
38 | /**
39 | * Initializes all defined services and starts the bluetooth server.
40 | */
41 | void init(const String &obsName,
42 | uint16_t leftOffset, uint16_t rightOffset,
43 | std::function batteryPercentage,
44 | const String &trackId);
45 |
46 | /**
47 | * Starts advertising all services that internally implement shouldAdvertise()
48 | * with `true`. The bluetooth server needs to be started before this method.
49 | */
50 | void activateBluetooth();
51 |
52 | /**
53 | * Stops advertising the bluetooth services. The bluetooth server will not be
54 | * stopped.
55 | */
56 | void deactivateBluetooth() const;
57 |
58 | /**
59 | * Disconnects the currently connected device/client.
60 | */
61 | void disconnectDevice() const;
62 |
63 | /**
64 | * Processes new sensor values by calling each services with the values.
65 | * @param millis sender millis counter at the time of measurement of the left value
66 | * @param leftValue sensor value of the left side (MAX_SENSOR_VALUE for no reading)
67 | * @param rightValues sensor value of the right side (MAX_SENSOR_VALUE for no reading)
68 | */
69 | void newSensorValues(uint32_t millis, uint16_t leftValue, uint16_t rightValue);
70 |
71 | /**
72 | * Processes new confirmed pass event.
73 | * @param millis sender millis counter at the time of measurement of the left value
74 | * @param leftValue sensor value of the left side (MAX_SENSOR_VALUE for no reading)
75 | * @param rightValues sensor value of the right side (MAX_SENSOR_VALUE for no reading)
76 | */
77 | void newPassEvent(uint32_t millis, uint16_t leftValue, uint16_t rightValue);
78 |
79 | /* True if any client is currently connected. */
80 | bool hasConnectedClients();
81 |
82 | private:
83 | BLEServer *pServer;
84 | std::list services;
85 | void onDisconnect(BLEServer *pServer) override;
86 | void onConnect(BLEServer *pServer) override;
87 | void setFastAdvertising();
88 | void setSlowAdvertising();
89 | bool deviceConnected;
90 | bool fastAdvertising;
91 | uint32_t lastDisconnected;
92 | static const uint32_t HIGH_ADVERTISEMENT_TIME_MS;
93 |
94 | };
95 |
96 | #endif
97 |
--------------------------------------------------------------------------------
/src/utils/streams.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "streams.h"
25 |
26 | // StringStream
27 |
28 | StringStream::StringStream(String str) {
29 | string = std::move(str);
30 | }
31 |
32 | int StringStream::available() {
33 | return string.length() - pos;
34 | }
35 |
36 | int StringStream::read() {
37 | const int result = peek();
38 | if (result != -1) {
39 | pos++;
40 | }
41 | return result;
42 | }
43 |
44 | int StringStream::peek() {
45 | int result;
46 | if (pos >= string.length()) {
47 | result = -1;
48 | } else {
49 | result = string.charAt(pos);
50 | }
51 | return result;
52 | }
53 |
54 | void StringStream::flush() {
55 | }
56 |
57 | size_t StringStream::write(uint8_t) {
58 | return 0;
59 | }
60 |
61 | size_t StringStream::readBytes(char *buffer, size_t length) {
62 | size_t count;
63 | if (length > available()) {
64 | count = available();
65 | } else {
66 | count = length;
67 | }
68 | strncpy(buffer, string.c_str(), count);
69 | pos += count;
70 | return count;
71 | }
72 |
73 | // StreamOfStreams
74 |
75 | void StreamOfStreams::push(Stream *addedStream) {
76 | streams.push_back(addedStream);
77 | }
78 |
79 | int StreamOfStreams::available() {
80 | return getCurrent()->available();
81 | }
82 |
83 | int StreamOfStreams::read() {
84 | const int data = getCurrent()->read();
85 | if (data >= 0) {
86 | overallBytePos += 1;
87 | if (progressListener) {
88 | progressListener(overallBytePos);
89 | }
90 | }
91 | return data;
92 | }
93 |
94 | int StreamOfStreams::peek() {
95 | return getCurrent()->peek();
96 | }
97 |
98 | void StreamOfStreams::flush() {
99 | }
100 |
101 | size_t StreamOfStreams::write(uint8_t) {
102 | return 0;
103 | }
104 |
105 | size_t StreamOfStreams::readBytes(char *buffer, size_t length) {
106 | const size_t read = getCurrent()->readBytes(buffer, length);
107 | if (read > 0) {
108 | overallBytePos += read;
109 | if (progressListener) {
110 | progressListener(overallBytePos);
111 | }
112 | }
113 | return read;
114 | }
115 |
116 | void StreamOfStreams::setProgressListener(std::function listener) {
117 | progressListener = listener;
118 | }
119 |
120 |
121 | Stream *StreamOfStreams::getCurrent() {
122 | if (current == nullptr || current->available() == 0) {
123 | current = getNext();
124 | }
125 | return current;
126 | }
127 |
128 | Stream *StreamOfStreams::getNext() {
129 | if (pos < streams.size()) {
130 | current = streams.at(pos++);
131 | log_d("About to switch to stream %d/%d", pos, streams.size());
132 | } else {
133 | current = &EMPTY_STREAM;
134 | }
135 | return current;
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/src/bluetooth/ObsService.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "ObsService.h"
25 |
26 | const BLEUUID ObsService::OBS_SERVICE_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000000");
27 | const BLEUUID ObsService::OBS_TIME_CHARACTERISTIC_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000001");
28 | const BLEUUID ObsService::OBS_DISTANCE_CHARACTERISTIC_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000002");
29 | const BLEUUID ObsService::OBS_BUTTON_CHARACTERISTIC_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000003");
30 | const BLEUUID ObsService::OBS_OFFSET_CHARACTERISTIC_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000004");
31 | const BLEUUID ObsService::OBS_TRACK_ID_CHARACTERISTIC_UUID = BLEUUID("1FE7FAF9-CE63-4236-0004-000000000005");
32 |
33 | ObsService::ObsService(const uint16_t leftOffset, const uint16_t rightOffset, const String &trackId) {
34 | uint8_t offsets[4];
35 | memcpy(offsets, &leftOffset, 2);
36 | memcpy(&offsets[2], &rightOffset, 2);
37 | mOffsetCharacteristic.setValue(offsets, 4);
38 | mTrackIdCharacteristic.setValue(trackId.c_str());
39 | }
40 |
41 | void ObsService::setup(BLEServer *pServer) {
42 | // Each characteristic needs 2 handles and descriptor 1 handle.
43 | mService = pServer->createService(OBS_SERVICE_UUID); // Keep the default, 18);
44 |
45 | mService->addCharacteristic(&mTimeCharacteristic);
46 | mTimeCharacteristic.setCallbacks(&mTimeCharacteristicsCallback);
47 |
48 | mService->addCharacteristic(&mDistanceCharacteristic);
49 | mDistanceCharacteristic.addDescriptor(&mDistanceConfiguration);
50 |
51 | mService->addCharacteristic(&mButtonCharacteristic);
52 | mButtonCharacteristic.addDescriptor(new BLE2902);
53 |
54 | mService->addCharacteristic(&mOffsetCharacteristic);
55 |
56 | mService->addCharacteristic(&mTrackIdCharacteristic);
57 | }
58 |
59 | bool ObsService::shouldAdvertise() {
60 | return true;
61 | }
62 |
63 | BLEService* ObsService::getService() {
64 | return mService;
65 | }
66 |
67 | void ObsService::newSensorValues(uint32_t millis, uint16_t leftValue, uint16_t rightValue) {
68 | if (mDistanceConfiguration.getNotifications()) {
69 | sendEventData(&mDistanceCharacteristic, millis, leftValue, rightValue);
70 | }
71 | }
72 |
73 | void ObsService::newPassEvent(uint32_t millis, uint16_t leftValue, uint16_t rightValue) {
74 | sendEventData(&mButtonCharacteristic, millis, leftValue, rightValue);
75 | }
76 |
77 | void ObsTimeServiceCallback::onRead(BLECharacteristic *pCharacteristic) {
78 | uint32_t value = millis();
79 | pCharacteristic->setValue(value);
80 | }
81 |
82 | void ObsService::sendEventData(BLECharacteristic *characteristic, uint32_t millis, uint16_t leftValue, uint16_t rightValue) {
83 | uint8_t event[8];
84 | memcpy(event, &millis, sizeof(millis));
85 | if (leftValue == MAX_SENSOR_VALUE) {
86 | leftValue = 0xffff;
87 | }
88 | memcpy(&event[4], &leftValue, sizeof(leftValue));
89 | if (rightValue == MAX_SENSOR_VALUE) {
90 | rightValue = 0xffff;
91 | }
92 | memcpy(&event[6], &rightValue, sizeof(rightValue));
93 | characteristic->setValue(event, 8);
94 | characteristic->notify();
95 | }
96 |
--------------------------------------------------------------------------------
/src/utils/obsutils.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "obsutils.h"
25 | #include
26 | #include "writer.h"
27 | #include "BLEServer.h"
28 |
29 | static const uint32_t BYTES_PER_KIB = 1 << 10;
30 | static const uint32_t BYTES_PER_MIB = 1 << 20;
31 | static const uint32_t BYTES_PER_GIB = 1 << 30;
32 |
33 | String ObsUtils::createTrackUuid() {
34 | uint8_t data[16];
35 | esp_fill_random(data, 16);
36 | return String(BLEUUID(data, 16, false).toString().c_str());
37 | }
38 |
39 | String ObsUtils::stripCsvFileName(const String &fileName) {
40 | String userPrintableFilename = fileName.substring(fileName.lastIndexOf("/") + 1);
41 | if (userPrintableFilename.endsWith(CSVFileWriter::EXTENSION)) {
42 | userPrintableFilename
43 | = userPrintableFilename.substring(
44 | 0, userPrintableFilename.length() - CSVFileWriter::EXTENSION.length());
45 | }
46 | return userPrintableFilename;
47 | }
48 |
49 | String ObsUtils::encodeForXmlAttribute(const String &text) {
50 | String result(text);
51 | result.replace("&", "&");
52 | result.replace("<", "<");
53 | result.replace(">", ">");
54 | result.replace("'", "'");
55 | result.replace("\"", """);
56 | return result;
57 | }
58 |
59 | String ObsUtils::encodeForXmlText(const String &text) {
60 | String result(text);
61 | result.replace("&", "&");
62 | result.replace("<", "<");
63 | return result;
64 | }
65 |
66 | String ObsUtils::encodeForCsvField(const String &field) {
67 | String result(field);
68 | result.replace(';', '_');
69 | result.replace('\n', ' ');
70 | result.replace('\r', ' ');
71 | return result;
72 | }
73 |
74 | // Poor man....
75 | String ObsUtils::encodeForUrl(const String &url) {
76 | String result(url);
77 | result.replace("%", "%25");
78 | result.replace("+", "%2B");
79 | result.replace(" ", "+");
80 | result.replace("\"", "%22");
81 | result.replace("\'", "%27");
82 | result.replace("=", "%3D");
83 | return result;
84 | }
85 |
86 | String ObsUtils::toScaledByteString(uint64_t size) {
87 | String result;
88 | if (size <= BYTES_PER_KIB * 10) {
89 | result = String((uint32_t) size) + "B";
90 | } else if (size <= BYTES_PER_MIB * 10) {
91 | result = String((uint32_t) (size >> 10)) + "KiB";
92 | } else if (size <= BYTES_PER_GIB * 10) {
93 | result = String((uint32_t) (size >> 20)) + "MiB";
94 | } else {
95 | result = String((uint32_t) (size >> 30)) + "GiB";
96 | }
97 | return result;
98 | }
99 |
100 | void ObsUtils::logHexDump(const uint8_t *buffer, uint16_t length) {
101 | ESP_LOG_BUFFER_HEXDUMP(__FILE__, buffer, length, ESP_LOG_WARN);
102 | }
103 |
104 | String ObsUtils::sha256ToString(byte *sha256) {
105 | const int HASH_LEN = 32;
106 | char hash_print[HASH_LEN * 2 + 1];
107 | hash_print[HASH_LEN * 2] = 0;
108 | for (int i = 0; i < HASH_LEN; ++i) {
109 | snprintf(&hash_print[i * 2], 3, "%02x", sha256[i]);
110 | }
111 | return String(hash_print);
112 | }
113 |
114 | String ObsUtils::to3DigitString(uint32_t value) {
115 | String val = String(value);
116 | if (value <= 9) {
117 | val = "00" + val;
118 | } else if (value >= 10 && value <= 99) {
119 | val = "0" + val;
120 | } // no overflow
121 | return val;
122 | }
--------------------------------------------------------------------------------
/docs/software/firmware/obs_cfg.md:
--------------------------------------------------------------------------------
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 display config, see DisplayOptions for details,
36 | // as noted all subject to change!
37 | "displayConfig": 15,
38 | // PIN to be entered when accessing the OBS web interface.
39 | // a new one will be created when empty. The PIN is also displayed
40 | // on the OBS display when needed.
41 | "httpPin": "12345678",
42 | // Textual name of the profile - waiting for features to come.
43 | "name": "default",
44 | // Name of the OBS, will be used for WiFo, Bluetooth and other places
45 | // currently no way to change it, consists of OpenBikeSensor-
46 | "obsName": "OpenBikeSensor-cafe",
47 | // The handle bar offset in cm, order right, left.
48 | "offset": [
49 | 31,
50 | 32
51 | ],
52 | // Token used to authenticate and authorize at the portal.
53 | "portalToken": "thisIsAlsoSecret",
54 | // URL of the portal to be used
55 | "portalUrl": "https://portal.openbikesensor.org",
56 | // Array with privacy areas to be considered
57 | "privacyArea": [
58 | {
59 | // latitude of the entered value, for documentation and display purpose only
60 | "lat": 48.001,
61 | // shifted latitude used for position filtering
62 | "latT": 48.00105,
63 | // longitude of the entered value, for documentation and display purpose only
64 | "long": 9.001,
65 | // shifted longitude used for position filtering
66 | "longT": 9.001121,
67 | // radius in meters around the position to be filtered
68 | "radius": 101
69 | }
70 | ],
71 | // Bitfield for the privacy configuration see PrivacyOptions
72 | "privacyConfig": 10,
73 | // Active preset - always 0 as of today
74 | "selectedPreset": 0,
75 | // Deprecated: Password of your Wi-Fi where the OBS should log into in server mode
76 | "wifiPassword": "swordfish",
77 | // Deprecated: SSID of your Wi-Fi where the OBS should log into in server mode
78 | "wifiSsid": "obs-cloud",
79 | // Array with multiple Wi-Fi networks to be used in client mode
80 | "wifiNetworks": [
81 | {
82 | // Password of your Wi-Fi where the OBS should log into in client mode
83 | "wifiPassword": "swordfish",
84 | // SSID of your Wi-Fi where the OBS should log into in client mode
85 | "wifiSsid": "obs-cloud",
86 | // if true obs will allow unprotected access in this network
87 | "wifiPrivate": true
88 | }
89 | ]
90 | }
91 | ]
92 | }
93 | ```
94 |
95 |
--------------------------------------------------------------------------------
/src/gpsrecord.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "gpsrecord.h"
25 |
26 | void GpsRecord::reset(uint32_t tow, uint32_t gpsWeek, uint32_t createdAtMillisTicks) {
27 | mCollectTow = tow;
28 | mCollectWeek = gpsWeek;
29 | mCreatedAtMillisTicks = createdAtMillisTicks;
30 | mLatitude = 0;
31 | mLongitude = 0;
32 | mCourseOverGround = 0;
33 | mSatellitesUsed = 0;
34 | mFixStatus = GPS_FIX::NO_FIX;
35 | mFixStatusFlags = 0;
36 | mHdop = 0;
37 | mHeight = 0;
38 | mSpeed = 0;
39 | mPositionSet = false;
40 | mVelocitySet = false;
41 | mInfoSet = false;
42 | mHdopSet = false;
43 | }
44 |
45 | void GpsRecord::setWeek(uint32_t week) {
46 | mCollectWeek = week;
47 | }
48 |
49 | void GpsRecord::setPosition(int32_t lon, int32_t lat, int32_t height) {
50 | mLongitude = lon;
51 | mLatitude = lat;
52 | mHeight = height;
53 | mPositionSet = true;
54 | }
55 |
56 | void GpsRecord::setVelocity(uint32_t speedOverGround, int32_t heading) {
57 | mSpeed = speedOverGround;
58 | mCourseOverGround = heading;
59 | mVelocitySet = true;
60 | }
61 |
62 | void GpsRecord::setInfo(uint8_t satellitesInUse, GPS_FIX gpsFix, uint8_t flags) {
63 | mSatellitesUsed = satellitesInUse;
64 | mFixStatus = gpsFix;
65 | mFixStatusFlags = flags;
66 | mInfoSet = true;
67 | }
68 |
69 | void GpsRecord::setHdop(uint16_t hDop) {
70 | mHdop = hDop;
71 | mHdopSet = true;
72 | }
73 |
74 | bool GpsRecord::isAllSet() const {
75 | return mPositionSet && mVelocitySet && mInfoSet && mHdopSet;
76 | }
77 |
78 | uint32_t GpsRecord::getTow() const {
79 | return mCollectTow;
80 | }
81 |
82 | uint32_t GpsRecord::getWeek() const {
83 | return mCollectWeek;
84 | }
85 |
86 | String GpsRecord::getAltitudeMetersString() const {
87 | // 3 digits is problematic, 2 are enough any way.
88 | return toScaledString((mHeight + 5) / 10, 2);
89 | }
90 |
91 | String GpsRecord::getCourseString() const {
92 | return toScaledString(mCourseOverGround, 5);
93 | }
94 |
95 | String GpsRecord::getSpeedKmHString() const {
96 | return toScaledString((mSpeed * 60 * 60) / 10000, 1);
97 | }
98 |
99 | String GpsRecord::getHdopString() const {
100 | return toScaledString(mHdop, 2);
101 | }
102 |
103 |
104 | const int32_t GpsRecord::pow10[] = {
105 | 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
106 | };
107 |
108 | String GpsRecord::toScaledString(const int32_t value, const uint16_t scale) {
109 | if (value == 0) {
110 | return "";
111 | }
112 | char buffer[32];
113 | const int32_t scl = pow10[scale];
114 | snprintf(buffer, sizeof(buffer), "%d.%0*d", value / scl, scale, abs(value % scl) );
115 | return String(buffer);
116 | }
117 |
118 | bool GpsRecord::hasValidFix() const {
119 | return (mFixStatus == FIX_2D || mFixStatus == FIX_3D || mFixStatus == GPS_AND_DEAD_RECKONING)
120 | && mHdop != 9999 && mSatellitesUsed != 0;
121 | }
122 |
123 | String GpsRecord::getLatString() const {
124 | return toScaledString(mLatitude, 7);
125 | }
126 |
127 | String GpsRecord::getLongString() const {
128 | return toScaledString(mLongitude, 7);
129 | }
130 |
131 | double GpsRecord::getLatitude() const {
132 | return ((double) mLatitude) / 10000000.0;
133 | }
134 |
135 | double GpsRecord::getLongitude() const {
136 | return ((double) mLongitude) / 10000000.0;
137 | }
138 |
139 | uint8_t GpsRecord::getSatellitesUsed() const {
140 | return mSatellitesUsed;
141 | }
142 |
143 | GpsRecord::GPS_FIX GpsRecord::getFixStatus() const {
144 | return mFixStatus;
145 | }
146 |
147 | uint32_t GpsRecord::getCreatedAtMillisTicks() const {
148 | return mCreatedAtMillisTicks;
149 | }
150 |
151 | uint8_t GpsRecord::getFixStatusFlags() const {
152 | return mFixStatusFlags;
153 | }
154 |
--------------------------------------------------------------------------------
/src/fonts/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | https://openfontlicense.org
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/docs/software/firmware/bluetooth_services.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Bluetooth Services
4 | parent: Firmware
5 | grand_parent: Software
6 | ---
7 |
8 | # Overview
9 |
10 | | Service | UUID | Description |
11 | | ----------- | -------------------------------------- | ------------------------------------------------------------------ |
12 | | Device Info | `0000180A-0000-1000-8000-00805F9B34FB` | General information about the bluetooth device |
13 | | OBS | `1FE7FAF9-CE63-4236-0004-000000000000` | Reports distance sensor readings and confirmed close passes |
14 | | Heart Rate | `0000180D-0000-1000-8000-00805F9B34FB` | Transmits the current distance by acting like a heart rate monitor |
15 |
16 |
17 | ## Device Info Service
18 | - *Description:* General information about the bluetooth device
19 | - *UUID:* `0000180A-0000-1000-8000-00805F9B34FB`
20 |
21 | | Characteristic | UUID | Property | Value |
22 | | ----------------- | -------------------------------------- | -------- | ------------------ |
23 | | Firmware Revision | `00002a26-0000-1000-8000-00805f9b34fb` | `READ` | `vX.Y.ZZZZ` |
24 | | Manufacturer Name | `00002a29-0000-1000-8000-00805f9b34fb` | `READ` | `openbikesensor.org` |
25 |
26 |
27 | ## OBS Service
28 | - *Description:* Transmits current sensor readings
29 | - *UUID:* `1FE7FAF9-CE63-4236-0004-000000000000`
30 |
31 | | Characteristic | UUID | Property | Value |
32 | | ------------------- | -------------------------------------- | --------------- | ----------------------------------------------------------------------------------- |
33 | | Time | `1FE7FAF9-CE63-4236-0004-000000000001` | `READ` | reports the value of the ms timer of the OBS unit, can be used to synchronize time |
34 | | Sensor Distance | `1FE7FAF9-CE63-4236-0004-000000000002` | `NOTIFY` | Gives sensor reading of the left and right sensor. |
35 | | Close Pass | `1FE7FAF9-CE63-4236-0004-000000000003` | `NOTIFY` | Notifies of button confirmed close pass events. |
36 | | Offset | `1FE7FAF9-CE63-4236-0004-000000000004` | `READ` | Configured handle bar offset values in cm. |
37 | | Track Id | `1FE7FAF9-CE63-4236-0004-000000000005` | `READ` | UUID as text to uniquely identify the current recorded track. |
38 |
39 | This service uses binary format to transfer time counter as unit32 and unt16
40 | for distance in cm.
41 |
42 | *Time* is sent as uint32. The time counts linear milliseconds from the start
43 | of the obs. The value returned is the timer value at the time of the read.
44 |
45 | *Sensor Distance* delivers the time of the left measurement with the current values of
46 | the left and right sensor. Content is time uint32, left uint16, right uint16. Left
47 | and right values are in cm, a value of `0xffff` means no measurement. The message is
48 | sent immediately after the measure, so you can assume that the reported time
49 | is current at the ESP.
50 |
51 | *Close Pass* events are triggered when a pass was confirmed by button press. The
52 | values are same as with the *Sensor Distance* characteristic. Note that this
53 | information is sent after confirmation, so the timer information must be used
54 | to match the event to the correct time and so location.
55 |
56 | *Offset* reports the configured handle bar offsets in cm on the OBS side. This
57 | is purely to ease the user configuration. The offset is not considered in any
58 | of the other reported values. The service uses 2 uint16 values to report the
59 | left and right offset in cm in that order.
60 |
61 | *Tack Id* holds a UUID as String representation that can be used to uniquely
62 | identify the recorded track. If the value changes, a new track is recorded, and
63 | the millisecond counter on the OBS likely is restarted.
64 |
65 | ## Heart Rate Service
66 | - *Description:* Transmits the current distance by acting like a heart rate monitor
67 | - *UUID:* `0000180D-0000-1000-8000-00805F9B34FB`
68 |
69 | | Characteristic | UUID | Property | Value |
70 | | --------------- | -------------------------------------- | ---------------- | ----------------------------------------- |
71 | | Heart Rate | `00002a37-0000-1000-8000-00805f9b34fb` | `NOTIFY` | Minimum distance measured over 1/2 second |
72 |
73 |
--------------------------------------------------------------------------------
/src/utils/multipart.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "multipart.h"
25 |
26 | MultipartData::MultipartData(String name, String contentType) {
27 | this->name = std::move(name);
28 | this->contentType = std::move(contentType);
29 | }
30 |
31 | String MultipartData::getBaseHeaders(const String& fileName) {
32 | String headers = "Content-Disposition: form-data; name=\"" + name + "\"";
33 | if (!fileName.isEmpty()) {
34 | headers += "; filename=\"" + fileName + "\"";
35 | }
36 | headers += "\r\n";
37 | if (!contentType.isEmpty()) {
38 | headers += "Content-Type: " + contentType + "\r\n";
39 | }
40 | return headers;
41 | }
42 |
43 |
44 | MultipartDataString::MultipartDataString(String name, const String& content, String contentType)
45 | : MultipartData(std::move(name), std::move(contentType)), contentStream(content) {
46 | this->content = content;
47 | }
48 |
49 | String MultipartDataString::getHeaders() {
50 | return getBaseHeaders();
51 | }
52 |
53 | Stream *MultipartDataString::asStream() {
54 | return &
55 | contentStream;
56 | }
57 |
58 | size_t MultipartDataString::length() {
59 | return content.length();
60 |
61 | }
62 |
63 | String MultipartDataStream::getHeaders() {
64 | return getBaseHeaders(fileName);
65 | }
66 |
67 | Stream *MultipartDataStream::asStream() {
68 | return content;
69 | }
70 |
71 | size_t MultipartDataStream::length() {
72 | return content->size();
73 | }
74 |
75 | MultipartDataStream::MultipartDataStream(String name, String fileName, File *content, String contentType)
76 | : MultipartData(std::move(name), std::move(contentType)) {
77 | this->fileName = std::move(fileName);
78 | this->content = content;
79 | }
80 |
81 |
82 | MultipartStream::MultipartStream(HTTPClient *client) {
83 | this->httpClient = client;
84 | boundary = "----" + String(esp_random(), 16) + String(esp_random(), 16);
85 | httpClient->addHeader("Content-Type",
86 | "multipart/form-data; boundary=" + boundary);
87 | }
88 |
89 | MultipartStream::~MultipartStream() {
90 | for (const auto stream : myStreams) {
91 | delete stream;
92 | }
93 | myStreams.clear();
94 | }
95 |
96 | size_t MultipartStream::predictSize() const {
97 | return length;
98 | }
99 |
100 | void MultipartStream::add(MultipartData &newData) {
101 | String preamble = "\r\n--" + boundary + "\r\n"
102 | + newData.getHeaders() + "\r\n";
103 | Stream *preambleStream = new StringStream(preamble);
104 | streams.push(preambleStream);
105 | myStreams.push_back(preambleStream);
106 | streams.push(newData.asStream());
107 | length += preamble.length();
108 | length += newData.length();
109 | log_d("Adding new part, size: %d", newData.length());
110 | }
111 |
112 | // API is bad - client must make sure to call last after the last add
113 | void MultipartStream::last() {
114 | String conclusion = "\r\n--" + boundary + "--\r\n";
115 | Stream *conclusionStream = new StringStream(conclusion);
116 | streams.push(conclusionStream);
117 | myStreams.push_back(conclusionStream);
118 | length += conclusion.length();
119 | }
120 |
121 | int MultipartStream::available() {
122 | return streams.available();
123 | }
124 |
125 | int MultipartStream::read() {
126 | return streams.read();
127 | }
128 |
129 | int MultipartStream::peek() {
130 | return streams.peek();
131 | }
132 |
133 | void MultipartStream::flush() {
134 | }
135 |
136 | size_t MultipartStream::write(uint8_t) {
137 | return 0;
138 | }
139 |
140 | size_t MultipartStream::readBytes(char *buffer, size_t readLength) {
141 | return streams.readBytes(buffer, readLength);
142 | }
143 |
144 | void MultipartStream::setProgressListener(std::function listener) {
145 | streams.setProgressListener(listener);
146 | }
147 |
--------------------------------------------------------------------------------
/src/VoltageMeter.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "VoltageMeter.h"
25 | #include "globals.h"
26 |
27 | /* Class to encapsulate voltage readings and smoothing thereof.
28 | * Still the values are not as accurate as expected, and it is not
29 | * clear if this is a error in the code or limitation of the ESP.
30 | * I read() 3.96V for 4.02V on my cheep voltage meter.
31 | *
32 | * We might add features like a trend (charging/discharging) and
33 | * possibly guess percentage later. We also need a "alert" threshold
34 | * where we just save all end exit.
35 | * Using ESP32 calls not arduino lib calls here.
36 | * ESPCode: https://github.com/espressif/esp-idf/blob/master/components/esp_adc_cal/include/esp_adc_cal.h
37 | */
38 | VoltageMeter::VoltageMeter(uint8_t batteryPin, adc1_channel_t channel) :
39 | mBatteryPin(batteryPin), mBatteryAdcChannel(channel) {
40 | log_i("Initializing VoltageMeter.");
41 | pinMode(mBatteryPin, INPUT);
42 | ESP_ERROR_CHECK_WITHOUT_ABORT(
43 | adc1_config_width(ADC_WIDTH_BIT_12));
44 | // Suggested range for ADC_ATTEN_DB_11 is 150 - 2450 mV, we are a bit above 4.22V * 2/3 == 2.81V
45 | // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#api-reference
46 | ESP_ERROR_CHECK_WITHOUT_ABORT(
47 | adc1_config_channel_atten(mBatteryAdcChannel, ADC_ATTEN_DB_11));
48 | __unused const esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
49 | ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12,
50 | REF_VOLTAGE_MILLI_VOLT, &adc_chars);
51 | if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
52 | log_i("Characterized using Two Point Value");
53 | } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
54 | log_i("Characterized using eFuse Vref");
55 | } else {
56 | log_i("Characterized using Default Vref");
57 | }
58 | //Check if TP is burned into eFuse
59 | if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
60 | log_i("eFuse Two Point: Supported");
61 | } else {
62 | log_i("eFuse Two Point: NOT supported");
63 | }
64 | //Check Vref is burned into eFuse
65 | if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
66 | log_i("eFuse Vref: Supported");
67 | } else {
68 | log_i("eFuse Vref: NOT supported");
69 | }
70 | lastSmoothedReading = readRaw();
71 | for (int i = 0; i < MINIMUM_SAMPLES; i++) {
72 | readSmoothed();
73 | yield();
74 | }
75 | log_i("VoltageMeter initialized got %03.2fV.", read());
76 | }
77 |
78 | bool VoltageMeter::isWarningLevel() {
79 | return hasReadings() && (read() < VoltageMeter::BATTERY_WARNING_LEVEL);
80 | }
81 |
82 | bool VoltageMeter::hasReadings() {
83 | return read() > VoltageMeter::BATTERY_NO_READ_LEVEL;
84 | }
85 |
86 | double VoltageMeter::read() {
87 | return esp_adc_cal_raw_to_voltage(readSmoothed(), &adc_chars)
88 | * 3.0 / 2000.0; // voltage divider @ OSB PCB
89 | }
90 |
91 | int8_t VoltageMeter::readPercentage() {
92 | if (!hasReadings()) {
93 | return -1;
94 | }
95 | auto voltage = read();
96 | int8_t percentage;
97 | if (voltage > 4.13) {
98 | percentage = 100;
99 | } else if (voltage > 3.67) { // 100% - 50%
100 | percentage = 108.696 * voltage - 348.914;
101 | } else if (voltage > 3.49) { // 50% - 25%
102 | percentage = 138.889 * voltage - 459.723;
103 | } else if (voltage > 3.12) { // 25% - 0%
104 | percentage = 67.568 * voltage - 210.812;
105 | } else {
106 | percentage = 0;
107 | }
108 | log_v("VoltageMeter: %.2fV %d%%", voltage, percentage);
109 | return percentage;
110 | }
111 |
112 | int VoltageMeter::readSmoothed() {
113 | lastSmoothedReading =
114 | (lastSmoothedReading * (SAMPLES_DIVIDE - 1) + readRaw()) / SAMPLES_DIVIDE;
115 | return lastSmoothedReading;
116 | }
117 |
118 | int VoltageMeter::readRaw() const {
119 | return adc1_get_raw(mBatteryAdcChannel);
120 | }
121 |
--------------------------------------------------------------------------------
/src/uploader.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "uploader.h"
25 |
26 | #include "globals.h"
27 | #include "utils/multipart.h"
28 | #include "utils/timeutils.h"
29 | #include "writer.h"
30 |
31 | // https://docs.platformio.org/en/latest/platforms/espressif32.html#embedding-binary-data
32 | extern const uint8_t x509_crt_bundle_start[] asm("_binary_src_truststore_x509_crt_bundle_start");
33 |
34 | static char const *const HTTP_LOCATION_HEADER = "location";
35 |
36 | Uploader::Uploader(String portalUrl, String userToken) :
37 | mPortalUrl(std::move(portalUrl)),
38 | mPortalUserToken(std::move(userToken)) {
39 | TimeUtils::setClockByNtpAndWait();
40 | mWiFiClient.setCACertBundle(x509_crt_bundle_start);
41 | }
42 |
43 | /* Upload file as track data to "The Portal" as multipart form data.
44 | */
45 | bool Uploader::upload(const String& fileName) {
46 | bool success = false;
47 | if(fileName.substring(0,7) != "/sensor"
48 | && !fileName.endsWith(CSVFileWriter::EXTENSION)) {
49 | log_e("Not sending %s wrong extension.", fileName.c_str());
50 | mLastStatusMessage = "Not sending " + fileName + " wrong extension.";
51 | } else {
52 | log_d("Sending '%s'.", fileName.c_str());
53 | File csvFile = SD.open(fileName.c_str(), "r");
54 | if (csvFile) {
55 | success = uploadFile(csvFile);
56 | csvFile.close();
57 | } else {
58 | log_e("file %s not found", fileName.c_str());
59 | mLastStatusMessage = "File " + fileName + " not found!";
60 | }
61 | }
62 | return success;
63 | }
64 |
65 | bool Uploader::uploadFile(File &file) {
66 | bool success = false;
67 | HTTPClient https;
68 | https.setTimeout(30 * 1000); // give the api some time
69 | https.setUserAgent(String("OBS/") + String(OBSVersion));
70 |
71 | const char* headers[] = { HTTP_LOCATION_HEADER };
72 | https.collectHeaders(headers, 1);
73 | if (https.begin(mWiFiClient, mPortalUrl + "/api/tracks")) { // HTTPS
74 | https.addHeader("Authorization", "OBSUserId " + mPortalUserToken);
75 | https.addHeader("Content-Type", "application/json");
76 | const String fileName = file.name();
77 | const String displayFileName = ObsUtils::stripCsvFileName(fileName);
78 | MultipartStream mp(&https);
79 | MultipartDataString title("title", "AutoUpload " + displayFileName);
80 | mp.add(title);
81 | MultipartDataString description("description", "Uploaded with OpenBikeSensor " + String(OBSVersion));
82 | mp.add(description);
83 | MultipartDataStream data("body", fileName, &file, "text/csv");
84 | mp.add(data);
85 | mp.last();
86 | const size_t contentLength = mp.predictSize();
87 | mp.setProgressListener([contentLength](size_t pos) {
88 | obsDisplay->drawProgressBar(5, pos, contentLength);
89 | });
90 |
91 | int httpCode = https.sendRequest("POST", &mp, contentLength);
92 |
93 | mLastStatusMessage = String(httpCode) + ": ";
94 | if (httpCode < 0) {
95 | mLastStatusMessage += HTTPClient::errorToString(httpCode);
96 | // This might be a large body, could be any wrong web url configured!
97 | } else if (https.getSize() < 1024) {
98 | mLastStatusMessage += https.getString();
99 | } else {
100 | mLastStatusMessage += "Length: " + String(https.getSize());
101 | }
102 | mLastLocation = https.header(HTTP_LOCATION_HEADER);
103 | if (httpCode == 200 || httpCode == 201) {
104 | log_v("HTTP OK %s", mLastStatusMessage.c_str());
105 | success = true;
106 | } else {
107 | log_e("HTTP Error %s", mLastStatusMessage.c_str());
108 | https.end();
109 | }
110 | } else {
111 | mLastStatusMessage = "[HTTPS] begin to " + mPortalUrl + " failed.";
112 | log_e("HTTPS error %s", mLastStatusMessage.c_str());
113 | https.end();
114 | }
115 | return success;
116 | }
117 |
118 | String Uploader::getLastStatusMessage() const {
119 | return mLastStatusMessage;
120 | }
121 |
122 | String Uploader::getLastLocation() const {
123 | return mLastLocation;
124 | }
125 |
--------------------------------------------------------------------------------
/src/bluetooth/BluetoothManager.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "BluetoothManager.h"
25 |
26 | const uint32_t BluetoothManager::HIGH_ADVERTISEMENT_TIME_MS = 60 * 1000;
27 |
28 | void BluetoothManager::init(
29 | const String &obsName,
30 | const uint16_t leftOffset, const uint16_t rightOffset,
31 | std::function batteryPercentage,
32 | const String &trackId) {
33 |
34 | deviceConnected = false;
35 | ESP_ERROR_CHECK_WITHOUT_ABORT(
36 | esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
37 | BLEDevice::init(obsName.c_str());
38 | pServer = BLEDevice::createServer();
39 | pServer->setCallbacks(this);
40 |
41 | services.push_back(new DeviceInfoService);
42 | services.push_back(new HeartRateService);
43 | services.push_back(new BatteryService(batteryPercentage));
44 | services.push_back(new ObsService(leftOffset, rightOffset, trackId));
45 |
46 | for (auto &service : services) {
47 | service->setup(pServer);
48 | }
49 | for (auto &service : services) {
50 | service->getService()->start();
51 | }
52 | lastDisconnected = millis();
53 | }
54 |
55 | void BluetoothManager::activateBluetooth() {
56 | auto adv = pServer->getAdvertising();
57 |
58 | // only the heard rate service && OBS service use advertisement
59 | // if I add one more service the 0x12 info is not sent.
60 | for (auto &service : services) {
61 | if (service->shouldAdvertise()) {
62 | adv->addServiceUUID(service->getService()->getUUID());
63 | }
64 | }
65 | setFastAdvertising();
66 |
67 | // Save some bytes in the advertising payload
68 | // https://specificationrefs.bluetooth.com/assigned-values/Appearance%20Values.pdf
69 | // adv->setAppearance(1152); // Generic: Cycling
70 |
71 | // causes 0x12 Slave Connection Interval Range to be sent
72 | adv->setMinPreferred(0x06); // Apple?
73 | adv->setMaxPreferred(0x12);
74 |
75 | BLEDevice::startAdvertising();
76 | }
77 |
78 | void BluetoothManager::deactivateBluetooth() const {
79 | pServer->getAdvertising()->stop();
80 | }
81 |
82 | void BluetoothManager::disconnectDevice() const {
83 | pServer->disconnect(pServer->getConnId());
84 | }
85 |
86 | void BluetoothManager::newSensorValues(const uint32_t millis, const uint16_t leftValues, const uint16_t rightValues) {
87 | if (deviceConnected) {
88 | for (auto &service : services) {
89 | service->newSensorValues(millis, leftValues, rightValues);
90 | }
91 | } else if (lastDisconnected + HIGH_ADVERTISEMENT_TIME_MS < millis) {
92 | setSlowAdvertising();
93 | }
94 | }
95 |
96 | void BluetoothManager::newPassEvent(const uint32_t millis, const uint16_t leftValue, const uint16_t rightValue) {
97 | log_i("BLE new pass event at %d, left: %dcm, right: %dcm", millis, leftValue, rightValue);
98 | if (deviceConnected) {
99 | for (auto &service : services) {
100 | service->newPassEvent(millis, leftValue, rightValue);
101 | }
102 | }
103 | }
104 |
105 | bool BluetoothManager::hasConnectedClients() {
106 | return pServer->getConnectedCount() != 0;
107 | }
108 |
109 | void BluetoothManager::onConnect(BLEServer* pServer) {
110 | log_i("BTLE connected!");
111 | deviceConnected = true;
112 | };
113 |
114 | void BluetoothManager::onDisconnect(BLEServer* pServer) {
115 | log_i("BTLE disconnected!");
116 | lastDisconnected = millis();
117 | deviceConnected = false;
118 | setFastAdvertising();
119 | pServer->startAdvertising();
120 | }
121 |
122 | void BluetoothManager::setFastAdvertising() {
123 | auto adv = pServer->getAdvertising();
124 | adv->setMinInterval(48 /* 0.625 msec = 30ms */);
125 | adv->setMaxInterval(80 /* 0.625 msec = 50ms */);
126 | fastAdvertising = true;
127 | }
128 |
129 | void BluetoothManager::setSlowAdvertising() {
130 | if (fastAdvertising) {
131 | log_i("Decreasing BTLE advertisement interval.");
132 | auto adv = pServer->getAdvertising();
133 | adv->stop();
134 | adv->setMinInterval(800 /* 0.625 msec = 500ms */);
135 | adv->setMaxInterval(1280 /* 0.625 msec = 800ms */);
136 | adv->start();
137 | fastAdvertising = false;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/sensor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_SENSOR_H
25 | #define OBS_SENSOR_H
26 |
27 | #include
28 | #include
29 |
30 | #include "variant.h"
31 | #include "globals.h"
32 | #include "utils/median.h"
33 |
34 | /* About the speed of sound:
35 | See also http://www.sengpielaudio.com/Rechner-schallgeschw.htm (german)
36 | - speed of sound depends on ambient temperature
37 | temp, Celsius speed, m/sec int factor dist error introduced with fix int factor of 58
38 | (331.5+(0.6*t)) (2000/speed) (speed@58 / speed) - 1
39 | 35 352.1 (57) -2.1% (-3.2cm bei 150cm)
40 | 30 349.2
41 | 25 346.3
42 | 22.4 344.82 58 0
43 | 20 343.4
44 | 15 340.5
45 | 12.5 338.98 (59) +1.7% (2.6cm bei 150)
46 | 10 337.5
47 | 5 334.5
48 | 0 331.5 (60) +4% (6cm bei 150cm)
49 | −5 328.5
50 | −10 325.4
51 | −15 322.3
52 | */
53 |
54 | struct HCSR04SensorInfo {
55 | uint8_t triggerPin = 15;
56 | uint8_t echoPin = 4;
57 | uint16_t offset = 0;
58 | uint16_t rawDistance = 0;
59 | uint16_t distances[MEDIAN_DISTANCE_MEASURES] = { MAX_SENSOR_VALUE, MAX_SENSOR_VALUE, MAX_SENSOR_VALUE };
60 | uint16_t nextMedianDistance = 0;
61 | uint16_t minDistance = MAX_SENSOR_VALUE;
62 | uint16_t distance = MAX_SENSOR_VALUE;
63 | char* sensorLocation;
64 | // timestamp when the trigger signal was sent in us micros()
65 | uint32_t trigger = 0;
66 | volatile uint32_t start = 0;
67 | /* if end == 0 - a measurement is in progress */
68 | volatile uint32_t end = 1;
69 |
70 | int32_t echoDurationMicroseconds[MAX_NUMBER_MEASUREMENTS_PER_INTERVAL + 1];
71 | Median*median = nullptr;
72 | // statistics
73 | uint32_t maxDurationUs = 0;
74 | uint32_t minDurationUs = UINT32_MAX;
75 | uint32_t lastDelayTillStartUs = 0;
76 | // counts how often no echo and also no timeout signal was received
77 | // should only happen with defect or missing sensors
78 | uint32_t numberOfNoSignals = 0;
79 | uint32_t numberOfLowAfterMeasurement = 0;
80 | uint32_t numberOfToLongMeasurement = 0;
81 | uint32_t numberOfInterruptAdjustments = 0;
82 | uint16_t numberOfTriggers = 0;
83 | bool measurementRead;
84 | };
85 |
86 | class HCSR04SensorManager {
87 | public:
88 | HCSR04SensorManager() {}
89 | virtual ~HCSR04SensorManager() {}
90 | void reset(uint32_t startMillisTicks);
91 | void registerSensor(const HCSR04SensorInfo &, uint8_t idx);
92 | void setOffsets(std::vector);
93 | void setPrimarySensor(uint8_t idx);
94 | void detachInterrupts();
95 | void attachInterrupts();
96 | /* Returns the current raw median distance in cm for the
97 | * given sensor.
98 | */
99 | uint16_t getRawMedianDistance(uint8_t sensorId);
100 | /* Index for CSV. */
101 | uint16_t getCurrentMeasureIndex();
102 | uint32_t getMaxDurationUs(uint8_t sensorId);
103 | uint32_t getMinDurationUs(uint8_t sensorId);
104 | uint32_t getLastDelayTillStartUs(uint8_t sensorId);
105 | uint32_t getNoSignalReadings(const uint8_t sensorId);
106 | uint32_t getNumberOfLowAfterMeasurement(const uint8_t sensorId);
107 | uint32_t getNumberOfToLongMeasurement(const uint8_t sensorId);
108 | uint32_t getNumberOfInterruptAdjustments(const uint8_t sensorId);
109 |
110 | HCSR04SensorInfo m_sensors[NUMBER_OF_TOF_SENSORS];
111 | uint16_t sensorValues[NUMBER_OF_TOF_SENSORS];
112 | uint16_t lastReadingCount = 0;
113 | uint16_t startOffsetMilliseconds[MAX_NUMBER_MEASUREMENTS_PER_INTERVAL + 1];
114 | bool pollDistancesParallel();
115 | bool pollDistancesAlternating();
116 |
117 | protected:
118 |
119 | private:
120 | void sendTriggerToSensor(uint8_t sensorId);
121 | bool collectSensorResult(uint8_t sensorId);
122 | void setSensorTriggersToLow();
123 | bool collectSensorResults();
124 | void attachSensorInterrupt(uint8_t idx);
125 | uint32_t getFixedStart(size_t idx, HCSR04SensorInfo * const sensor);
126 | boolean isReadyForStart(uint8_t sensorId);
127 | void registerReadings();
128 | static uint16_t medianMeasure(HCSR04SensorInfo* const sensor, uint16_t value);
129 | static uint16_t median(uint16_t a, uint16_t b, uint16_t c);
130 | static uint16_t correctSensorOffset(uint16_t dist, uint16_t offset);
131 | static uint32_t microsBetween(uint32_t a, uint32_t b);
132 | static uint32_t microsSince(uint32_t a);
133 | static uint16_t millisSince(uint16_t milliseconds);
134 | static void updateStatistics(HCSR04SensorInfo * const sensor);
135 | uint32_t startReadingMilliseconds = 0;
136 | uint8_t primarySensor = 1;
137 | uint8_t lastSensor;
138 | };
139 |
140 | #endif
141 |
--------------------------------------------------------------------------------
/src/obsimprov.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OPENBIKESENSORFIRMWARE_OBSIMPROV_H
25 | #define OPENBIKESENSORFIRMWARE_OBSIMPROV_H
26 |
27 | /* TODO:
28 | * - provide short documentation (on index.html?)
29 | * - refactor as lib?
30 | */
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | /**
37 | * Utility class to implement the improv protocol.
38 | * See protocol documentation at https://www.improv-wifi.com/serial/ for
39 | * the specification of the protocol.
40 | */
41 | class ObsImprov {
42 | public:
43 | enum class State : uint8_t {
44 | READY = 0x02,
45 | PROVISIONING = 0x03,
46 | PROVISIONED = 0x04,
47 | };
48 |
49 | /**
50 | * Create a new ObsImprov instance, able to handle incoming messages.
51 | * All callback methods must be expected to be called from "handle()"
52 | * call.
53 | *
54 | * @param initWifi callback method if new wifi data was received via improv.
55 | * must return true if a connection could be established.
56 | * @param getWifiStatus should return the status of the wifi connection.
57 | * @param getDeviceUrl if the device wifi is up the url needed to reach
58 | * the device should be returned, a empty string otherwise.
59 | */
60 | ObsImprov(std::function initWifi,
61 | std::function getWifiStatus,
62 | std::function getDeviceUrl,
63 | HardwareSerial* serial = &Serial) :
64 | mSerial(serial),
65 | mInitWifi(initWifi),
66 | mWifiStatus(getWifiStatus),
67 | mDeviceUrl(getDeviceUrl) { };
68 |
69 | /**
70 | * Check for new chars on serial.
71 | */
72 | void handle();
73 |
74 | /**
75 | * Consume given char as if it had been read from serial.
76 | * Can be used if there are several parties interested in serial data.
77 | * @param c the char to be consumed.
78 | */
79 | void handle(char c);
80 |
81 | /**
82 | * Store detailed device information.
83 | * Should be called as soon as possible after creating a ObsImprov instance.
84 | * Empty data is reported upstream if needed earlier.
85 | */
86 | void setDeviceInfo(const std::string & firmwareName,
87 | const std::string & firmwareVersion,
88 | const std::string & hardwareVariant,
89 | const std::string & deviceName);
90 |
91 | /**
92 | * Returns true if any improv message was received.
93 | * @return true if a improv message was received at any time
94 | */
95 | bool isActive() const;
96 |
97 | private:
98 | enum class Type : uint8_t {
99 | CURRENT_STATE = 0x01,
100 | ERROR_STATE = 0x02,
101 | RPC_COMMAND = 0x03,
102 | RPC_RESULT = 0x04
103 | };
104 | enum class Command : uint8_t {
105 | WIFI_SETTINGS = 0x01,
106 | GET_CURRENT_STATE = 0x02,
107 | GET_DEVICE_INFO = 0x03,
108 | GET_WIFI_NETWORKS = 0x04
109 | };
110 | enum class Error : uint8_t {
111 | NOBE = 0x00,
112 | INVALID_RPC = 0x01,
113 | UNKNOWN_RPC = 0x02,
114 | UNABLE_TO_CONNECT = 0x03,
115 | UNKNOWN = 0xFF
116 | };
117 | enum class Offset : uint8_t {
118 | TYPE = 0x00,
119 | LENGTH = 0x01,
120 | RPC_COMMAND = 0x02,
121 | RPC_DATA_LENGTH = 0x03,
122 | RPC_DATA_1 = 0x04
123 | };
124 | HardwareSerial* mSerial;
125 | std::vector mBuffer;
126 | uint8_t mHeaderPos = 0;
127 | std::string mFirmwareName;
128 | std::string mFirmwareVersion;
129 | std::string mHardwareVariant;
130 | std::string mDeviceName;
131 | static const char *HEADER;
132 | static const uint8_t HEADER_LENGTH;
133 | const std::function mInitWifi;
134 | const std::function mWifiStatus;
135 | const std::function mDeviceUrl;
136 | bool mImprovActive = false;
137 | void sendWifiSuccess(Command cmd = Command::WIFI_SETTINGS) const;
138 | void sendCurrentState(State state) const;
139 | void sendErrorState(Error error) const;
140 | void handleRpcGetDeviceInfo() const;
141 | void appendStringAndLength(std::vector &response, std::string data) const;
142 | void sendPayload(Stream *stream, std::vector payload) const;
143 | bool isCompleteImprovMessage(std::vector buffer) const;
144 | bool isValidImprovMessage(std::vector buffer) const;
145 | void handleImprovMessage(std::vector buffer);
146 | void handleRpcWifiSettings(std::vector &buffer) const;
147 | void handleRpcGetCurrentState() const;
148 | void handleRpcGetWifiNetworks() const;
149 | void handleImprovBody();
150 | };
151 |
152 |
153 | #endif //OPENBIKESENSORFIRMWARE_OBSIMPROV_H
154 |
--------------------------------------------------------------------------------
/src/utils/https.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "https.h"
25 | #include
26 | #include
27 | #include "esp_task_wdt.h"
28 |
29 | using namespace httpsserver;
30 |
31 | static volatile bool isCertReady = false;
32 |
33 | // "20190101000000"
34 | static std::string toCertDate(time_t theTime) {
35 | char date[32];
36 | tm timeStruct;
37 | localtime_r(&theTime, &timeStruct);
38 | snprintf(date, sizeof(date),
39 | "%04d%02d%02d%02d%02d%02d",
40 | timeStruct.tm_year + 1900, timeStruct.tm_mon + 1, timeStruct.tm_mday,
41 | timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
42 | return std::string(date);
43 | }
44 |
45 | static std::string createDn() {
46 | char dn[128];
47 | const uint64_t chipid_num = ESP.getEfuseMac();
48 | // Placed the date in here - firefox does complain about duplicate cert
49 | // otherwise (we can not increase the serial number from here).
50 | snprintf(dn, sizeof(dn),
51 | "CN=obs.local,O=openbikesensor.org,OU=%04x%08x,L=%s,C=DE",
52 | (uint16_t)(chipid_num >> 32),
53 | (uint32_t)(chipid_num),
54 | toCertDate(time(nullptr)).c_str());
55 | return std::string(dn);
56 | }
57 |
58 | static void createCert(void *param) {
59 | std::string fromDate;
60 | std::string toDate;
61 | time_t now = time(nullptr);
62 | if (now > (2020 - 1970) * 365 * 24 * 60 * 60) {
63 | fromDate = toCertDate(now);
64 | // Suggestion for hardware devices is to set the validity of the
65 | // cert to a high value. But Apple limits this value to 825
66 | // days in https://support.apple.com/HT210176
67 | toDate = toCertDate(now + 824 * 24 * 60 * 60);
68 | } else {
69 | fromDate = "20210513090700";
70 | toDate = "20301231235959";
71 | }
72 |
73 | log_i("DN will be %s", createDn().c_str());
74 |
75 | SSLCert newCert;
76 | int res = createSelfSignedCert(newCert,
77 | KEYSIZE_2048,
78 | createDn(),
79 | fromDate,
80 | toDate);
81 | if (res != 0) {
82 | // Certificate generation failed. Inform the user.
83 | log_e("An error occurred during certificate generation.");
84 | log_e("Error code is 0x%04x", res);
85 | log_e("You may have a look at SSLCert.h to find the reason for this error.");
86 | } else {
87 | auto cert = static_cast(param);
88 | cert->setCert(newCert.getCertData(), newCert.getCertLength());
89 | cert->setPK(newCert.getPKData(), newCert.getPKLength());
90 | log_i("Created new cert.");
91 | }
92 | // Can this be done more elegant?
93 | isCertReady = true;
94 | vTaskDelete(nullptr);
95 | }
96 |
97 | bool Https::existsCertificate() {
98 | return SPIFFS.exists("/key.der") && SPIFFS.exists("/cert.der");
99 | }
100 |
101 | /* Load or create cert.
102 | * Based on https://github.com/fhessel/esp32_https_server/blob/de1876cf6fe717cf236ad6603a97e88f22e38d62/examples/REST-API/REST-API.ino#L219
103 | * https://github.com/fhessel/esp32_https_server/issues/48
104 | */
105 | SSLCert *Https::getCertificate(const std::function& progress) {
106 | // Try to open key and cert file to see if they exist
107 | File keyFile = SPIFFS.open("/key.der");
108 | File certFile = SPIFFS.open("/cert.der");
109 |
110 | // If now, create them
111 | if (!keyFile || !certFile || keyFile.size()==0 || certFile.size()==0) {
112 | log_i("No certificate found in SPIFFS, generating a new one.");
113 | log_i("This may take up to a minute, so please stand by :)");
114 |
115 | auto newCert = new SSLCert();
116 | xTaskCreate(reinterpret_cast(createCert), "createCert",
117 | 16 * 1024, newCert, 1, nullptr);
118 |
119 | while (!isCertReady) {
120 | if (progress) {
121 | progress();
122 | }
123 | delay(100);
124 | esp_task_wdt_reset();
125 | }
126 |
127 | bool failure = false;
128 | // Private key
129 | keyFile = SPIFFS.open("/key.der", FILE_WRITE);
130 | if (!keyFile || !keyFile.write(newCert->getPKData(), newCert->getPKLength())) {
131 | log_e("Could not write /key.der");
132 | failure = true;
133 | }
134 | if (keyFile) keyFile.close();
135 |
136 | // Certificate
137 | certFile = SPIFFS.open("/cert.der", FILE_WRITE);
138 | if (!certFile || !certFile.write(newCert->getCertData(), newCert->getCertLength())) {
139 | log_e("Could not write /cert.der");
140 | failure = true;
141 | }
142 | if (certFile) certFile.close();
143 |
144 | if (failure) {
145 | log_e("Certificate could not be stored permanently, generating new certificate on reboot...");
146 | }
147 | return newCert;
148 | } else {
149 | log_i("Reading certificate from SPIFFS.");
150 |
151 | // The files exist, so we can create a certificate based on them
152 | size_t keySize = keyFile.size();
153 | size_t certSize = certFile.size();
154 |
155 | auto keyBuffer = new uint8_t[keySize];
156 | if (keyBuffer == nullptr) {
157 | log_e("Not enough memory to load privat key");
158 | return nullptr;
159 | }
160 | auto certBuffer = new uint8_t[certSize];
161 | if (certBuffer == nullptr) {
162 | delete[] keyBuffer;
163 | log_e("Not enough memory to load certificate");
164 | return nullptr;
165 | }
166 | keyFile.read(keyBuffer, keySize);
167 | certFile.read(certBuffer, certSize);
168 |
169 | keyFile.close();
170 | certFile.close();
171 | log_i("Read %u bytes of certificate and %u bytes of key from SPIFFS", certSize, keySize);
172 | return new SSLCert(certBuffer, certSize, keyBuffer, keySize);
173 | }
174 | }
175 |
176 | bool Https::removeCertificate() {
177 | SPIFFS.remove("/key.der");
178 | SPIFFS.remove("/cert.der");
179 | return !SPIFFS.exists("/key.der") && !SPIFFS.exists("/cert.der");
180 | }
181 |
--------------------------------------------------------------------------------
/src/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_CONFIG_H
25 | #define OBS_CONFIG_H
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | enum DisplayOptions {
33 | DisplaySatellites = 0x01, // 1
34 | DisplayVelocity = 0x02, // 2
35 | DisplayLeft = 0x04, // 4
36 | DisplayRight = 0x08, // 8
37 | DisplaySimple = 0x10, // 16
38 | DisplaySwapSensors = 0x20, // 32
39 | DisplayInvert = 0x40, // 64
40 | DisplayFlip = 0x80, // 128
41 | DisplayNumConfirmed = 0x100, //256
42 | DisplayDistanceDetail = 0x200 // 512
43 | };
44 |
45 | enum GPSOptions {
46 | ValidLocation = 0x01, //1
47 | ValidTime = 0x02, //2
48 | NumberSatellites = 0x04 //4
49 | };
50 |
51 | enum PrivacyOptions {
52 | AbsolutePrivacy = 0x01, //1
53 | NoPosition = 0x02, //2
54 | NoPrivacy = 0x04, //4
55 | OverridePrivacy = 0x08 //8
56 | };
57 |
58 | struct WifiConfig {
59 | String ssid = "";
60 | String password = "";
61 | bool trusted = false;
62 | };
63 |
64 | struct PrivacyArea {
65 | double latitude;
66 | double longitude;
67 | double transformedLatitude;
68 | double transformedLongitude;
69 | double radius;
70 | };
71 |
72 | // Most values should be moved away from here to the concrete implementation
73 | // which uses the value
74 | struct Config {
75 | char obsName[32];
76 | std::vector sensorOffsets;
77 | char hostname[64];
78 | char obsUserID[64];
79 | uint displayConfig;
80 | bool bluetooth;
81 | int privacyConfig;
82 | int confirmationTimeWindow;
83 | std::vector privacyAreas;
84 | std::vector wifiConfigs;
85 | };
86 |
87 | enum DevOptions {
88 | ShowGrid = 0x01,
89 | PrintWifiPassword = 0x02
90 | };
91 |
92 | class ObsConfig {
93 | public:
94 | ObsConfig() : jsonData(4096) {};
95 | ~ObsConfig() = default;
96 | bool loadConfig();
97 | bool loadConfig(File &file);
98 | bool saveConfig() const;
99 | void printConfig() const;
100 | bool removeConfig();
101 |
102 | std::vector getIntegersProperty(String const &name) const;
103 | template T getProperty(const String &key) const;
104 | bool setBitMaskProperty(int profile, const String &key, uint value, bool state);
105 | uint getBitMaskProperty(int profile, const String &key, uint mask) const;
106 |
107 | bool setProperty(int profile, const String &key, std::string const &value);
108 | bool setProperty(int profile, const String &key, String const &value);
109 | bool setProperty(int profile, const String &key, bool const &value);
110 | bool setProperty(int profile, const String &key, int const &value);
111 | template bool setProperty(int profile, const String &key, T const &value);
112 | bool setOffsets(int profile, std::vector const &value);
113 |
114 | bool setPrivacyArea(int profile, int paId, PrivacyArea const &pa);
115 | bool addPrivacyArea(int profile, PrivacyArea const &pa);
116 | bool removePrivacyArea(int profile, int paId);
117 | PrivacyArea getPrivacyArea(int profile, int paId) const;
118 | int getNumberOfPrivacyAreas(int profile) const;
119 | WifiConfig getWifiConfig(int wifiId) const;
120 | int getNumberOfWifiConfigs() const;
121 | bool removeWifiConfig(int wifiId);
122 | bool addWifiConfig(WifiConfig const &wifiConfig);
123 | bool setWifiConfig(int wifiId, WifiConfig const &wifiConfig);
124 |
125 | int getNumberOfProfiles() const;
126 | int addProfile();
127 | bool deleteProfile(int profile);
128 | bool selectProfile(int profile);
129 | int getSelectedProfile() const;
130 | String getProfileName(int profile); // = getProperty(profile, "name")
131 |
132 | void fill(Config &cfg) const;
133 | /* free memory allocated by json document. */
134 | void releaseJson();
135 | String asJsonString() const;
136 | bool parseJson(const String &json);
137 |
138 | static const String PROPERTY_OBS_NAME;
139 | static const String PROPERTY_NAME;
140 | static const String PROPERTY_BLUETOOTH;
141 | static const String PROPERTY_OFFSET;
142 | static const String PROPERTY_SIM_RA;
143 | static const String PROPERTY_WIFI_SSID;
144 | static const String PROPERTY_WIFI_PASSWORD;
145 | static const String PROPERTY_WIFI_NETWORKS;
146 | static const String PROPERTY_WIFI_PRIVATE;
147 | static const String PROPERTY_PORTAL_TOKEN;
148 | static const String PROPERTY_PORTAL_URL;
149 | static const String PROPERTY_DISPLAY_CONFIG;
150 | static const String PROPERTY_CONFIRMATION_TIME_SECONDS;
151 | static const String PROPERTY_PRIVACY_CONFIG;
152 | static const String PROPERTY_SELECTED_PRESET;
153 | static const String PROPERTY_PRIVACY_AREA;
154 | static const String PROPERTY_PA_LAT;
155 | static const String PROPERTY_PA_LONG;
156 | static const String PROPERTY_PA_LAT_T;
157 | static const String PROPERTY_PA_LONG_T;
158 | static const String PROPERTY_PA_RADIUS;
159 | static const String PROPERTY_HTTP_PIN;
160 |
161 | private:
162 | static bool loadJson(JsonDocument &jsonDocument, const String &filename);
163 | static bool loadJson(JsonDocument &jsonDocument, fs::File &file);
164 | static bool parseJsonFromString(JsonDocument &jsonDocument, const String &jsonAsString);
165 | bool loadOldConfig(const String &filename);
166 | bool loadConfig(const String &filename);
167 | void parseOldJsonDocument(DynamicJsonDocument &document);
168 | void makeSureSystemDefaultsAreSet();
169 | template bool ensureSet(JsonObject data, const String &key, T value);
170 | JsonObject getProfile(int profile);
171 | JsonObjectConst getProfileConst(int profile) const;
172 | void resetJson();
173 |
174 | static const String CONFIG_OLD_FILENAME;
175 | static const String CONFIG_FILENAME;
176 |
177 | DynamicJsonDocument jsonData;
178 | int selectedProfile = 0;
179 | };
180 |
181 | #endif
182 |
--------------------------------------------------------------------------------
/src/utils/timeutils.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "timeutils.h"
25 |
26 | #include
27 | #include
28 |
29 |
30 | /* Flag character used when time was set according to GPS Time */
31 | static const char TIMEZONE_GPS = ' ';
32 | /* Flag character used when time was set according to UTC Time */
33 | static const char TIMEZONE_UTC = 'Z';
34 | /* Flag character used when time was not set */
35 | static const char TIMEZONE_UNKNOWN = 'X';
36 |
37 | // remember last timezone used, need to do it manually because GPS is not a
38 | // TimeZone in sense of linux supported time zones.
39 | static char timeZone = TIMEZONE_UNKNOWN;
40 |
41 |
42 | const uint32_t TimeUtils::SECONDS_PER_DAY = 60L * 60 * 24;
43 | const uint32_t TimeUtils::SECONDS_PER_WEEK = SECONDS_PER_DAY * 7;
44 | // use difftime() ?
45 | /* GPS Start time is 1980-01-06T00:00:00Z */
46 | const uint32_t TimeUtils::GPS_EPOCH_OFFSET = 315964800L;
47 |
48 |
49 | const time_t TimeUtils::PAST_TIME = 30 * 365 * 24 * 60 * 60;
50 | const char *TimeUtils::WEEK_DAYS[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
51 | const char *TimeUtils::MONTHS[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
52 |
53 |
54 | String TimeUtils::dateTimeToString(time_t timeIn) {
55 | char date[32];
56 | time_t theTime;
57 | if (timeIn == 0) {
58 | theTime = time(nullptr);
59 | } else {
60 | theTime = timeIn;
61 | }
62 | tm timeStruct;
63 | localtime_r(&theTime, &timeStruct);
64 | snprintf(date, sizeof(date),
65 | "%04d-%02d-%02dT%02d:%02d:%02d",
66 | timeStruct.tm_year + 1900, timeStruct.tm_mon + 1, timeStruct.tm_mday,
67 | timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
68 | String result(date);
69 | if (timeIn == 0 && timeZone == TIMEZONE_UTC) {
70 | result += TIMEZONE_UTC;
71 | }
72 | return result;
73 | }
74 |
75 | String TimeUtils::timeToString(time_t timeIn) {
76 | char date[32];
77 | time_t theTime;
78 | if (timeIn == 0) {
79 | theTime = time(nullptr);
80 | } else {
81 | theTime = timeIn;
82 | }
83 | if (theTime == 0) {
84 | theTime = time(nullptr);
85 | }
86 | tm timeStruct;
87 | localtime_r(&theTime, &timeStruct);
88 | snprintf(date, sizeof(date),
89 | "%02d:%02d:%02d",
90 | timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
91 | String result(date);
92 | if (timeIn == 0 && timeZone == TIMEZONE_UTC) {
93 | result += TIMEZONE_UTC;
94 | }
95 | return result;
96 | }
97 |
98 | String TimeUtils::dateTimeToHttpHeaderString(time_t theTime) {
99 | char date[32];
100 | if (theTime == 0) {
101 | theTime = time(nullptr);
102 | }
103 | tm timeStruct;
104 | localtime_r(&theTime, &timeStruct);
105 | snprintf(date, sizeof(date),
106 | "%s, %02d %s %04d %02d:%02d:%02d GMT",
107 | weekDayToString(timeStruct.tm_wday),
108 | timeStruct.tm_mday,
109 | monthToString(timeStruct.tm_mon),
110 | timeStruct.tm_year + 1900,
111 | timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
112 | return String(date);
113 | }
114 |
115 | const char* TimeUtils::weekDayToString(uint8_t wDay) {
116 | if (wDay > 6) {
117 | return "???";
118 | } else {
119 | return WEEK_DAYS[wDay];
120 | }
121 | }
122 |
123 | const char* TimeUtils::monthToString(uint8_t mon) {
124 | if (mon > 11) {
125 | return "???";
126 | } else {
127 | return MONTHS[mon];
128 | }
129 | }
130 |
131 | void TimeUtils::setClockByNtp(const char* ntpServer) {
132 | if (!systemTimeIsSet()) {
133 | if (ntpServer) {
134 | log_d("Got additional NTP Server %s.", ntpServer);
135 | configTime(
136 | 0, 0, ntpServer,
137 | "rustime01.rus.uni-stuttgart.de", "pool.ntp.org");
138 | } else {
139 | configTime(
140 | 0, 0,
141 | "rustime01.rus.uni-stuttgart.de", "pool.ntp.org");
142 | }
143 | }
144 | timeZone = TIMEZONE_UTC;
145 | }
146 |
147 | void TimeUtils::setClockByGps(uint32_t iTow, int32_t fTow, int16_t week, int8_t leapS) {
148 | const time_t gpsTime = toTime(week, iTow / 1000);
149 | if (timeZone == TIMEZONE_UTC && systemTimeIsSet()) {
150 | log_i("Ignore new GPS time (%s), already set via NTP (%s).",
151 | dateTimeToString(gpsTime).c_str(),
152 | dateTimeToString().c_str());
153 | return;
154 | }
155 | const int32_t gpsTimeUsec = ((iTow % 1000) * 1000) + (fTow / 1000);
156 | const struct timeval now = {
157 | .tv_sec = gpsTime,
158 | .tv_usec = gpsTimeUsec
159 | };
160 | settimeofday(&now, nullptr);
161 | timeZone = TIMEZONE_GPS;
162 | }
163 |
164 | void TimeUtils::setClockByNtpAndWait(const char* ntpServer, uint32_t timeoutMs) {
165 | setClockByNtp(ntpServer);
166 |
167 | log_i("Waiting %dms for NTP time sync. ", timeoutMs);
168 | const uint32_t startMs = millis();
169 | const uint32_t endMs = startMs + timeoutMs;
170 | while (!systemTimeIsSet() && (millis() < endMs)) {
171 | delay(100);
172 | }
173 | if (systemTimeIsSet()) {
174 | log_i("System time is set after %ums via NTP to %s.", millis() - startMs, dateTimeToString().c_str());
175 | } else {
176 | log_e("System time could not be set via NTP after %ums starting with %s.", millis() - startMs, dateTimeToString().c_str());
177 | }
178 | }
179 |
180 | bool TimeUtils::systemTimeIsSet() {
181 | time_t now = time(nullptr);
182 | log_v("time %s.", dateTimeToString(now).c_str());
183 | return now > 1609681614;
184 | }
185 |
186 | /* Determine the number of leap seconds to be considered at the given GPS
187 | * time.
188 | * TODO: Make this more fancy leverage AID_HUI info that can be stored on
189 | * SD or hardcode dates if announced at
190 | * https://www.ietf.org/timezones/data/leap-seconds.list
191 | */
192 | int16_t TimeUtils::getLeapSecondsGps(time_t gps) {
193 | return 18;
194 | }
195 |
196 | /* Determine the number of leap seconds to be considered at the given UTC
197 | * time.
198 | */
199 | int16_t TimeUtils::getLeapSecondsUtc(time_t utc) {
200 | return 18;
201 | }
202 |
203 | time_t TimeUtils::gpsDayToTime(uint16_t week, uint16_t dayOfWeek) {
204 | return (time_t) GPS_EPOCH_OFFSET + (SECONDS_PER_WEEK * week) + (SECONDS_PER_DAY * dayOfWeek);
205 | }
206 |
207 | time_t TimeUtils::toTime(uint16_t week, uint32_t weekTime) {
208 | return (time_t) GPS_EPOCH_OFFSET + (SECONDS_PER_WEEK * week) + weekTime;
209 | }
210 |
211 | uint32_t TimeUtils::utcTimeToTimeOfWeek(time_t t) {
212 | return (t - GPS_EPOCH_OFFSET - getLeapSecondsGps(t)) % SECONDS_PER_WEEK;
213 | }
214 |
215 | uint16_t TimeUtils::utcTimeToWeekNumber(time_t t) {
216 | return (t - GPS_EPOCH_OFFSET - getLeapSecondsGps(t)) / SECONDS_PER_WEEK;
217 | }
--------------------------------------------------------------------------------
/src/utils/alpdata.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include
25 | #include
26 | #include "globals.h"
27 | #include "alpdata.h"
28 | #include "timeutils.h"
29 |
30 | extern const uint8_t x509_crt_bundle_start[] asm("_binary_src_truststore_x509_crt_bundle_start");
31 |
32 | /* Download http://alp.u-blox.com/current_14d.alp (ssl?) if there is a new one
33 | * Takes 5 seconds to update the data.
34 | */
35 | void AlpData::update(DisplayDevice *display) {
36 | String lastModified = loadLastModified();
37 |
38 | File f = SD.open(ALP_DATA_FILE_NAME, FILE_READ);
39 | const time_t lastWrite = f.getLastWrite();
40 | if (!f || f.size() < ALP_DATA_MIN_FILE_SIZE ) {
41 | lastModified = "";
42 | } else if (lastWrite > TimeUtils::PAST_TIME &&
43 | time(nullptr) - lastWrite < 4 * 24 * 60 * 60) {
44 | log_d("File still current %s",
45 | TimeUtils::dateTimeToString(lastWrite).c_str());
46 | log_d("Now: %s",
47 | TimeUtils::dateTimeToString(time(nullptr)).c_str());
48 | log_d("Next Update: %s",
49 | TimeUtils::dateTimeToString(lastWrite + 4 * 24 * 60 * 60).c_str());
50 | f.close();
51 | display->showTextOnGrid(0, 5, "ALP not checked.");
52 | return;
53 | }
54 | f.close();
55 | log_d("Existing file last write %s", TimeUtils::dateTimeToString(f.getLastWrite()).c_str());
56 | log_d("Existing file is from %s", lastModified.c_str());
57 | display->showTextOnGrid(0, 5, "ALP data...");
58 |
59 | WiFiClientSecure wiFiClient;
60 | wiFiClient.setCACertBundle(x509_crt_bundle_start);
61 | HTTPClient httpClient;
62 | httpClient.begin(wiFiClient, ALP_DOWNLOAD_URL);
63 | const char *lastModifiedHeaderName = "Last-Modified";
64 | const char *headers[] = {lastModifiedHeaderName};
65 | httpClient.collectHeaders(headers, 1);
66 | // be polite - tell the server who we are
67 | httpClient.setUserAgent(String("openbikesensor.org/") + String(OBSVersion));
68 | if (!lastModified.isEmpty()) {
69 | httpClient.addHeader("If-Modified-Since", lastModified);
70 | }
71 | int httpCode = httpClient.GET();
72 | log_i("Size: %d", httpClient.getSize());
73 | if (httpCode == 200) {
74 | String newLastModified = httpClient.header(lastModifiedHeaderName);
75 | File newFile = SD.open(ALP_NEW_DATA_FILE_NAME, FILE_WRITE);
76 | const int written = httpClient.writeToStream(&newFile);
77 | newFile.close();
78 | log_e("Written: %d", written);
79 | if (written < ALP_DATA_MIN_FILE_SIZE) {
80 | displayHttpClientError(display, written);
81 | } else {
82 | log_e("Read %d bytes - all good! %s", written, newLastModified.c_str());
83 | SD.remove(ALP_DATA_FILE_NAME);
84 | SD.rename(ALP_NEW_DATA_FILE_NAME, ALP_DATA_FILE_NAME);
85 | saveLastModified(newLastModified);
86 | display->showTextOnGrid(0, 5, "ALP data updated!");
87 | }
88 | } else if (httpCode == 304) { // Not-Modified
89 | display->showTextOnGrid(0, 5, "ALP data was up to date.");
90 | log_i("All fine, not modified!");
91 | } else if (httpCode > 0) {
92 | display->showTextOnGrid(0,4, String("ALP data failed ") + String(httpCode).c_str());
93 | if (httpClient.getSize() < 200) {
94 | display->showTextOnGrid(0, 5, httpClient.getString().c_str());
95 | }
96 | } else {
97 | displayHttpClientError(display, httpCode);
98 | }
99 | httpClient.end();
100 | }
101 |
102 | void AlpData::displayHttpClientError(DisplayDevice *display, int httpError) {
103 | display->showTextOnGrid(0, 4, String("ALP data failed ") + String(httpError).c_str());
104 | String errorString = HTTPClient::errorToString(httpError);
105 | display->showTextOnGrid(0, 5, errorString.c_str());
106 | log_e("[HTTP] GET... failed, error %d: %s", httpError, errorString.c_str());
107 | }
108 |
109 | bool AlpData::available() {
110 | return SD.exists(LAST_MODIFIED_HEADER_FILE_NAME);
111 | }
112 |
113 | void AlpData::saveLastModified(const String &header) {
114 | File f = SD.open(LAST_MODIFIED_HEADER_FILE_NAME, FILE_WRITE);
115 | if (f) {
116 | f.print(header);
117 | f.close();
118 | }
119 | }
120 |
121 | String AlpData::loadLastModified() {
122 | File f = SD.open(LAST_MODIFIED_HEADER_FILE_NAME, FILE_READ);
123 | String lastModified = String();
124 | if (f) {
125 | lastModified = f.readString();
126 | }
127 | f.close();
128 | return lastModified;
129 | }
130 |
131 | uint16_t AlpData::fill(uint8_t *data, size_t ofs, uint16_t dataSize) {
132 | if (!mAlpDataFile) {
133 | mAlpDataFile = SD.open(ALP_DATA_FILE_NAME, FILE_READ);
134 | }
135 | int read = -1;
136 | if (mAlpDataFile.seek(ofs)) {
137 | read = mAlpDataFile.read(data, dataSize);
138 | }
139 | if (read <= 0) {
140 | log_e("Failed to read got %d.", read);
141 | mAlpDataFile.close();
142 | mAlpDataFile = SD.open(ALP_DATA_FILE_NAME, FILE_READ);
143 | if (mAlpDataFile.seek(ofs)) {
144 | read = mAlpDataFile.read(data, dataSize);
145 | }
146 | log_e("Read again: %d.", read);
147 | }
148 | // not closing the file saves 10ms per message
149 | // - need to take care when writing!
150 | return read;
151 | }
152 |
153 | /* Used to save AidIni data. */
154 | void AlpData::saveMessage(const uint8_t *data, size_t size) {
155 | File f = SD.open(AID_INI_DATA_FILE_NAME, FILE_WRITE);
156 | if (f) {
157 | size_t written = f.write(data, size);
158 | f.close();
159 | if (written != size) {
160 | log_e("Written only %d of %d bytes", written, size);
161 | } else {
162 | log_d("Written %d bytes", written);
163 | }
164 | }
165 | }
166 |
167 | /* Used to save AidIni data. */
168 | size_t AlpData::loadMessage(uint8_t *data, size_t size) {
169 | size_t result = 0;
170 | File f = SD.open(AID_INI_DATA_FILE_NAME, FILE_READ);
171 | if (f) {
172 | result = f.read(data, size);
173 | f.close();
174 | log_d("Read %d bytes", result);
175 | SD.remove(AID_INI_DATA_FILE_NAME);
176 | }
177 | return result;
178 | }
179 |
180 | void AlpData::save(const uint8_t *data, size_t offset, int length) {
181 | #ifdef RANDOM_ACCESS_FILE_AVAILAVLE
182 | // this is currently not possible to seek and modify data within an existing
183 | // file, we can only append :(
184 | if (!mAlpDataFile) {
185 | mAlpDataFile = SD.open(ALP_DATA_FILE_NAME, FILE_APPEND);
186 | }
187 | int written = -99;
188 | if (mAlpDataFile.seek(offset)) {
189 | written = mAlpDataFile.write(data, length);
190 | }
191 | if (written <= 0) {
192 | log_e("Failed to write got %d.", written);
193 | mAlpDataFile.close();
194 | mAlpDataFile = SD.open(ALP_DATA_FILE_NAME, FILE_APPEND);
195 | if (mAlpDataFile.seek(offset)) {
196 | written = mAlpDataFile.write(data, length);
197 | }
198 | log_e("Write again: %d.", written);
199 | }
200 | #endif
201 | }
202 |
--------------------------------------------------------------------------------
/src/Firmware.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 | #include "Arduino.h"
24 | #include "Firmware.h"
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | // https://docs.platformio.org/en/latest/platforms/espressif32.html#embedding-binary-data
32 | extern const uint8_t x509_crt_bundle_start[] asm("_binary_src_truststore_x509_crt_bundle_start");
33 |
34 | static const String FLASH_APP_FILENAME("/sdflash/app.bin");
35 | static const String OPEN_BIKE_SENSOR_FLASH_APP_PROJECT_NAME("OpenBikeSensorFlash");
36 | static const size_t APP_PARTITION_SIZE = 0x380000; // read from part?
37 | static const int SHA256_HASH_LEN = 32;
38 |
39 | // todo: error handling
40 | void Firmware::downloadToSd(String url, String filename, bool unsafe) {
41 | WiFiClientSecure client;
42 | if (!unsafe) client.setCACertBundle(x509_crt_bundle_start);
43 | else client.setInsecure();
44 | HTTPClient http;
45 | http.setUserAgent(mUserAgent);
46 | http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
47 |
48 | if (http.begin(client, url)) {
49 | int status = http.GET();
50 | log_i("Opening %s got %d.", url.c_str(), status);
51 | log_i("http size: %d. ", http.getSize());
52 | log_i("Will access Stream:, free heap %dkb", ESP.getFreeHeap() / 1024);
53 | if (status == 200) {
54 | File newFile = SD.open(filename, FILE_WRITE);
55 | int written = http.writeToStream(&newFile);
56 | newFile.close();
57 | log_i("Got %d bytes", written);
58 | }
59 | }
60 | http.end();
61 | }
62 |
63 | bool Firmware::downloadToFlash(String url,
64 | std::function progress,
65 | bool unsafe) {
66 | bool success = false;
67 | WiFiClientSecure client;
68 | if (!unsafe) client.setCACertBundle(x509_crt_bundle_start);
69 | else client.setInsecure();
70 | HTTPClient http;
71 | http.setUserAgent(mUserAgent);
72 | http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
73 | if (http.begin(client, url)) {
74 | progress(0, 999);
75 | int status = http.GET();
76 | log_i("Opening %s got %d.", url.c_str(), status);
77 | size_t size = http.getSize();
78 | log_i("http size: %d. ", size);
79 | log_i("Will access Stream:, free heap %dkb", ESP.getFreeHeap() / 1024);
80 | if (status == HTTP_CODE_OK) {
81 | Update.begin();
82 | Update.onProgress([progress, size](size_t pos, size_t all) {
83 | progress(pos, size);
84 | });
85 |
86 | Stream& stream = http.getStream();
87 | byte buffer[256];
88 | size_t read;
89 | size_t written = 0;
90 | while ((read = stream.readBytes(&buffer[0], sizeof(buffer))) > 0) {
91 | Update.write(buffer, read);
92 | written += read;
93 | }
94 | log_i("Got %d bytes", written);
95 | } else {
96 | log_e("Got http status: %d", status);
97 | http.end();
98 | return false;
99 | }
100 | }
101 | http.end();
102 | if (Update.end(true)) { //true to set the size to the current progress
103 | mLastMessage = "Success";
104 |
105 | // Suppress the ota Firmware switch!
106 | const esp_partition_t *running = esp_ota_get_running_partition();
107 | esp_ota_set_boot_partition(running);
108 | success = true;
109 | } else {
110 | mLastMessage = Update.errorString();
111 | log_e("Update: %s", mLastMessage.c_str());
112 | }
113 | return success;
114 | }
115 |
116 | String Firmware::getLastMessage() {
117 | return mLastMessage;
118 | };
119 |
120 | const esp_partition_t* Firmware::findEspFlashAppPartition() {
121 | const esp_partition_t *part
122 | = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, nullptr);
123 |
124 | esp_app_desc_t app_desc;
125 | esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
126 |
127 | if (ret != ESP_OK || OPEN_BIKE_SENSOR_FLASH_APP_PROJECT_NAME != app_desc.project_name) {
128 | part
129 | = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1,
130 | nullptr);
131 | ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
132 | }
133 |
134 | if (ret == ESP_OK && OPEN_BIKE_SENSOR_FLASH_APP_PROJECT_NAME == app_desc.project_name) {
135 | return part;
136 | } else {
137 | return nullptr;
138 | }
139 | }
140 |
141 | String Firmware::getFlashAppVersion() {
142 | const esp_partition_t *part = findEspFlashAppPartition();
143 | esp_app_desc_t app_desc;
144 | esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
145 | String version;
146 | if (ret == ESP_OK) {
147 | version = app_desc.version;
148 | }
149 | return version;
150 | }
151 |
152 | static void calculateSha256(File &f, uint8_t *shaResult, int32_t bytes) {
153 | mbedtls_md_context_t ctx;
154 | mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
155 | mbedtls_md_init(&ctx);
156 | mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
157 | mbedtls_md_starts(&ctx);
158 |
159 | const uint16_t bufferSize = 8192;
160 | uint8_t *buffer = static_cast(malloc(bufferSize));
161 | uint32_t toRead = bufferSize;
162 | uint32_t read;
163 | uint32_t readFromFile = 0;
164 | while ((read = f.read(buffer, toRead)) > 0) {
165 | mbedtls_md_update(&ctx, buffer, read);
166 | readFromFile += read;
167 | if (readFromFile + toRead > bytes) {
168 | toRead = bytes - readFromFile;
169 | }
170 | }
171 | free(buffer);
172 | mbedtls_md_finish(&ctx, shaResult);
173 | mbedtls_md_free(&ctx);
174 | }
175 |
176 | String Firmware::checkSdFirmware() {
177 | String error;
178 | File f = SD.open(FLASH_APP_FILENAME, FILE_READ);
179 | if (!f) {
180 | error = "Failed to find '" + FLASH_APP_FILENAME + "' on sd card.";
181 | return error;
182 | }
183 | const int32_t fileSize = f.size();
184 | if (fileSize > APP_PARTITION_SIZE) {
185 | error = "Firmware to flash is to large. ";
186 | } else {
187 | uint8_t shaResult[SHA256_HASH_LEN];
188 | calculateSha256(f, shaResult, fileSize - SHA256_HASH_LEN);
189 |
190 | for (int i = 0; i < SHA256_HASH_LEN; i++) {
191 | int c = f.read();
192 | if (shaResult[i] != c) {
193 | error = "Checksum mismatch.";
194 | break;
195 | }
196 | }
197 | }
198 | f.close();
199 | return error;
200 | }
201 |
202 | bool Firmware::switchToFlashApp() {
203 | bool success = false;
204 | const esp_partition_t *part = findEspFlashAppPartition();
205 | if (part) {
206 | success = (ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_set_boot_partition(part)) == ESP_OK);
207 | }
208 | return success;
209 | }
210 |
--------------------------------------------------------------------------------
/docs/software/firmware/csv_format.md:
--------------------------------------------------------------------------------
1 | # Format specification for the internal CSV format
2 |
3 | ## Encoding
4 |
5 | The whole data file is encoded as UTF-8. Writers of the file may choose not to use the whole unicode range for simplicity and restrict themselves to 7-bit ASCII for simplicity, because it is identical with UTF-8. The OBS does this for example, since it only produces data that can be encoded this way. Parsers should interpret the whole file as UTF-8 however, since other data sources may produce special characters inside the file, such as in free text comment fields.
6 |
7 | The file must not include a [BOM](https://de.wikipedia.org/wiki/Byte_Order_Mark).
8 |
9 | ## Metadata
10 |
11 | The 1st line of the CSV file contains key value metadata as URL encoded
12 | parameters. This line must be skipped to get a full CVS conform format.
13 | A sample line could look like follows:
14 |
15 | ```URL
16 | OBSFirmwareVersion=v0.3.999&OBSDataFormat=2&DataPerMeasurement=3&\
17 | MaximumMeasurementsPerLine=60&OffsetLeft=30&OffsetRight=30&\
18 | NumberOfDefinedPrivacyAreas=3&PrivacyLevelApplied=AbsolutePrivacy&\
19 | MaximumValidFlightTimeMicroseconds=18560&\
20 | DistanceSensorsUsed=HC-SR04/JSN-SR04T&DeviceId=ecec
21 | ```
22 |
23 | There might be new keys added. Parsers should ignore values they do not
24 | understand.
25 |
26 | | Key | Example value | Note |
27 | | --- | ------------- | ---- |
28 | | `OBSDataFormatVersion` | `2` | **Required**. This the version of this format specification that the file follows. |
29 | | `OBSFirmwareVersion` | `v0.3.999` | |
30 | | `DataPerMeasurement` | `3` | fix as of now is `Tms`, `Lus` and `Rus` |
31 | | `MaximumMeasurementsPerLine` | `60` | currently fix |
32 | | `HandlebarOffsetLeft` | `30` | as set in the configurations |
33 | | `HandlebarOffsetRight` | `30` | as set in the configurations |
34 | | `NumberOfDefinedPrivacyAreas` | `3` | as set in the configuration, just to be aware of |
35 | | `PrivacyLevelApplied` | `AbsolutePrivacy` | One of: NoPrivacy, NoPosition, OverridePrivacy, AbsolutePrivacy |
36 | | `MaximumValidFlightTimeMicroseconds` | `18560` | all echo times above this value must be discarded and treated as no object in sight |
37 | | `DistanceSensorsUsed` | `HC-SR04/JSN-SR04T` | enum currently only one possible value |
38 | | `DeviceId` | `affe` | internal Id of the OBS |
39 | | `PresetId` | `Wade` | Id to identify the selected preset. A owner might define multiple presets |
40 | | `BluetoothEnabled` | `1` | 1 if bluetooth is enabled, 0 otherwise
41 | | `TrackId` | `38605ba-76...` | A uuid that can be used to uniquely identify the track.
42 | | `TimeZone` | `GPS` | The time zone used to write Date and Time data. Typically this is GPS which is some leap seconds ahead of UTC (as of today 18). UTC is also a allowed value and the default if not TimeZone is given.
43 |
44 | ## CSV
45 |
46 | As 2nd line, the file contains a header line with headline entries for
47 | each field, the names must be the same as given in the table below.
48 | The number of data entries per line can differ.
49 |
50 | If there is no value in an entry this means no measurement or not
51 | available or hidden. Before we used `-1` or `NaN` for this, now we are
52 | less polite and save the space.
53 |
54 | There is typically one line per second, but there are possible exceptions:
55 | - Timing might be bad, and we miss one second, use the `Millis` field if
56 | you need more precise timings.
57 | - If we have multiple confirmed measurements in one interval in that case
58 | an interval appears multiple times - once with each confirmed value.
59 | Other fields are identical in both lines.
60 |
61 | The header defines the order of the fields, it can be different from
62 | the order here. Also fields that do not appear in the header must be
63 | assumed empty for the whole file.
64 |
65 |
66 | NOTE: The order of the fields is different from Version 1 of the CVS file.
67 |
68 | ### CSV-DIALECT
69 |
70 | Based on http://dataprotocols.org/csv-dialect/ the definition is:
71 |
72 | ```json
73 | {
74 | "csvddfVersion": 1.2,
75 | "delimiter": ";",
76 | "lineTerminator": "\n",
77 | "skipInitialSpace": true,
78 | "header": true
79 | }
80 | ```
81 |
82 | ### Data
83 |
84 | Headline | Format | Range | Sample | Description |
85 | --- | --- | --- | --- | --- |
86 | `Date` | TT.MM.YYYY | | 24.11.2020 | Time, typically as received by the GPS module. If there was no reception of a time signal yet, this might be unix time (starting 1.1.1970) which can be used as offset between the csv lines. Expect none linearity when time is set.
87 | `Time` | HH:MM:SS | | 12:00:00 | TimeZone is GPS or UTC according to the TimeZone metadata.
88 | `Millis` | int32 | 0-2^31 | 1234567 | Millisecond counter will continuously increase throughout the file, for time difference calculation
89 | `Comment` | char[] | | | Space to leave a short text comment
90 | `Latitude` | double | -90.0-90.0 | 42.123456 | Latitude as degrees
91 | `Longitude` | double | -180.0-180.0 | 9.123456 | Longitude in degrees
92 | `Altitude` | double | -9999.9-17999.9 | 480.12 | meters above mean sea level (GPGGA)
93 | `Course` | double | 0-359.9 | 42 | Course over ground in degrees (GPRMC)
94 | `Speed` | double | 0-359.9 | 42.0 | Speed over ground in km/h
95 | `HDOP` | double | 0-99.9 | 2.3 | Relative accuracy of horizontal position (GPGGA)
96 | `Satellites` | int16 | 0-99 | 5 | Number of satellites in use (GPGGA)
97 | `BatteryLevel` | double | 0-9.99 | 3.3 | Current battery level reading (~V)
98 | `Left` | int16 | 0-999 | 150 | Left minimum measured distance in centimeters of this line, the measurement is already corrected for the handlebar offset.
99 | `Right` | int16 | 0-999 | 150 | Right minimum measured distance as `Left` above.
100 | `Confirmed` | int32 | 0-60 | 5 | If !=0 the Measurement was confirmed overtaking by button press, contains the index `` of the related measurement
101 | `Marked` | char[] | | "OVERTAKING" | Measurement was marked (not possible yet) with the given tag use | to separate multiple tags is needed.
102 | `Invalid` | int16 | 0-1 | 1 | Measurement was marked as invalid reading (not possible yet)
103 | `InsidePrivacyArea`| int16 | 0-1 | 1 |
104 | `Factor` | double | | 58 | The factor used to calculate the time given in micro seconds (us) into centimeters (cm). Currently fix, might get adjusted by temperature some time later. |
105 | `Measurements` | int16 | 0-999 | 18 | Number of measurements entries in this line |
106 | _comment_ | | | | Now follows a series of #`Measurements` repetitions of #`DatasPerMeasurement` entries, `` is always increased starting from 1 for the 1st measurement. Order is always the same, additional data might be added to the end, `DatasPerMeasurement` will be increased then. |
107 | `Tms` | int16 | 0-1999 | 234 | Millisecond (ms) offset of measurement in this series (line) of measurements |
108 | `Lus` | int32 | 0-100000 | 3456 | Microseconds (us) till the echo was received by the left sensor, divide by the `Factor` given above to get the distance in centimeters you might also want to apply the handlebar offset given in the metadata. Empty for no measurement taken. Values above `MaximumValidFlightTimeMicroseconds` (metadata) point to a measurement timeout when there is no object in sight.|
109 | `Rus` | int32 | 0-100000 | 3456 | As `Lus` above for the right sensor. |
110 |
111 |
112 | Possible Header:
113 |
114 | ```csv
115 | Date;Time;Millis;Latitude;Longitude;Altitude; \
116 | Course;Speed;HDOP;Satellites;BatteryLevel;Left;Right;Confirmed;Marked;Invalid; \
117 | insidePrivacyArea;Factor;Measurements;Tms1;Lus1;Rus1;Tms2;Lus2;Rus2; \
118 | Tms3;Lus3;Rus3;...;Tms60;Lus60;Rus60
119 | ```
120 |
--------------------------------------------------------------------------------
/src/logo.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #ifndef OBS_LOGO_H
25 | #define OBS_LOGO_H
26 |
27 | #include
28 |
29 | #define OBSLogo_width 128
30 | #define OBSLogo_height 64
31 | const unsigned char OBSLogo [] PROGMEM = {
32 | // 'OBS Logo S, 128x64px
33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfc, 0xfc, 0x8d, 0x03,
43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
44 | 0xfc, 0xfd, 0x9d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 | 0x80, 0x03, 0x00, 0xee, 0xfc, 0xfd, 0x9d, 0x03, 0x00, 0x00, 0x00, 0x00,
46 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc6, 0x8c, 0x1d, 0x9c, 0x03,
47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc7,
48 | 0x8c, 0x1d, 0xbc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 | 0x80, 0xff, 0x3f, 0xc7, 0x8c, 0xfd, 0xbc, 0x03, 0x00, 0x00, 0x00, 0x00,
50 | 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x3f, 0xc7, 0xcc, 0xfd, 0xfc, 0x03,
51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x3f, 0xc7,
52 | 0xfc, 0xfd, 0xec, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 | 0x80, 0x03, 0x00, 0xc7, 0xfc, 0x1c, 0xec, 0x03, 0x00, 0x00, 0x00, 0x00,
54 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc7, 0x3c, 0x1c, 0xec, 0x03,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc6,
56 | 0x0c, 0x1c, 0xcc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 | 0x80, 0x03, 0x00, 0xe6, 0x0c, 0x1c, 0xcc, 0x03, 0x00, 0x00, 0x00, 0x00,
58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0c, 0xfc, 0x8d, 0x03,
59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
60 | 0x0c, 0xfc, 0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 | 0x00, 0x00, 0x00, 0x38, 0x0c, 0xfc, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x00,
62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 | 0x80, 0x07, 0x33, 0xc6, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x33, 0xe6, 0x0f, 0x00, 0x00, 0x00,
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x33, 0xe7,
68 | 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 | 0x80, 0x39, 0x33, 0xe3, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
70 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0xb3, 0xe3, 0x00, 0x00, 0x80, 0x03,
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x39, 0xf3, 0xe1,
72 | 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 | 0x80, 0x3f, 0xf3, 0xe1, 0xe7, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
74 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0xf3, 0xe1, 0xe7, 0xff, 0xff, 0x03,
75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf3, 0xe3,
76 | 0xe7, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 | 0x80, 0x39, 0xf3, 0xe3, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
78 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0x73, 0xe3, 0x00, 0x00, 0x80, 0x03,
79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0x33, 0xe7,
80 | 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 | 0x80, 0x39, 0x33, 0xe7, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
82 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x33, 0xee, 0x0f, 0x00, 0x00, 0x00,
83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x33, 0xee,
84 | 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 | 0x80, 0x07, 0x33, 0xcc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 | 0x00, 0x8f, 0x9f, 0x31, 0x3c, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
90 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x9f, 0x71, 0x7e, 0x7c, 0xfc, 0x00,
91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x9f, 0x73,
92 | 0x7f, 0xfe, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 | 0x80, 0x99, 0x83, 0x73, 0x27, 0xe6, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00,
94 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x81, 0x73, 0x03, 0xc7, 0x8c, 0x01,
95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x81, 0x77,
96 | 0x07, 0xc7, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 | 0x80, 0x87, 0x9f, 0x77, 0x1f, 0xc7, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00,
98 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x9f, 0x7f, 0x3e, 0xc7, 0xfc, 0x01,
99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x9f, 0x7d,
100 | 0x7c, 0xc7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 | 0x00, 0xbc, 0x81, 0x7d, 0x78, 0xc7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
102 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x81, 0x7d, 0x60, 0xc7, 0xcc, 0x00,
103 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x81, 0x79,
104 | 0x62, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 | 0x80, 0xb9, 0x9f, 0x79, 0x77, 0xee, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00,
106 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x9f, 0x71, 0x7f, 0x7e, 0xcc, 0x01,
107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x9f, 0x71,
108 | 0x3e, 0x7c, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 | 0x00, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 | 0x00, 0x00, 0x00, 0x00
119 | };
120 |
121 | #endif
122 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/src/displays.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2021 OpenBikeSensor Contributors
3 | * Contact: https://openbikesensor.org
4 | *
5 | * This file is part of the OpenBikeSensor firmware.
6 | *
7 | * The OpenBikeSensor firmware is free software: you can
8 | * redistribute it and/or modify it under the terms of the GNU
9 | * Lesser General Public License as published by the Free Software
10 | * Foundation, either version 3 of the License, or (at your option)
11 | * any later version.
12 | *
13 | * OpenBikeSensor firmware is distributed in the hope that
14 | * it will be useful, but WITHOUT ANY WARRANTY; without even the
15 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 | * PURPOSE. See the GNU Lesser General Public License for more
17 | * details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with the OpenBikeSensor firmware. If not,
21 | * see .
22 | */
23 |
24 | #include "displays.h"
25 |
26 | #include "fonts/logos.h"
27 |
28 | void DisplayDevice::showNumConfirmed() {
29 | String val = String(confirmedMeasurements);
30 | if (confirmedMeasurements <= 9) {
31 | val = "0" + val;
32 | }
33 | this->prepareTextOnGrid(2, 4, val, MEDIUM_FONT);
34 | this->prepareTextOnGrid(3, 5, "conf");
35 | }
36 |
37 | void DisplayDevice::showNumButtonPressed() {
38 | String val = String(numButtonReleased);
39 | if (numButtonReleased <= 9) {
40 | val = "0" + val;
41 | }
42 | this->prepareTextOnGrid(0, 4, val, MEDIUM_FONT);
43 | this->prepareTextOnGrid(1, 5, "press");
44 | }
45 |
46 | void DisplayDevice::displaySimple(uint16_t value) {
47 | if (value == MAX_SENSOR_VALUE) {
48 | this->prepareTextOnGrid(0, 0,
49 | "", HUGE_FONT, -7, 0);
50 | } else {
51 | this->prepareTextOnGrid(0, 0,
52 | ObsUtils::to3DigitString(value), HUGE_FONT, -7, 0);
53 | }
54 | this->prepareTextOnGrid(3, 2, "cm", MEDIUM_FONT, -7, -5);
55 | }
56 |
57 | void DisplayDevice::showValues(
58 | uint16_t sensor1MinDistance, const char* sensor1Location, uint16_t sensor1RawDistance,
59 | uint16_t sensor2MinDistance, const char* sensor2Location, uint16_t sensor2RawDistance, uint16_t sensor2Distance,
60 | uint16_t minDistanceToConfirm, int16_t batteryPercentage,
61 | int16_t TemperaturValue, int lastMeasurements, boolean insidePrivacyArea,
62 | double speed, uint8_t satellites) {
63 |
64 | handleHighlight();
65 |
66 | uint16_t value1 = sensor1MinDistance;
67 | if (minDistanceToConfirm != MAX_SENSOR_VALUE) {
68 | value1 = minDistanceToConfirm;
69 | }
70 | if (config.displayConfig & DisplaySimple) {
71 | displaySimple(value1);
72 | } else {
73 | if (config.displayConfig & DisplayLeft) {
74 | String loc1 = sensor1Location;
75 | if (insidePrivacyArea) {
76 | loc1 = "(" + loc1 + ")";
77 | }
78 | this->prepareTextOnGrid(0, 0, loc1);
79 | if (value1 == MAX_SENSOR_VALUE) {
80 | this->prepareTextOnGrid(0, 1, "---", LARGE_FONT);
81 | } else {
82 | this->prepareTextOnGrid(0, 1,
83 | ObsUtils::to3DigitString(value1), LARGE_FONT);
84 | }
85 | }
86 | // Show sensor2, when DisplayRight is configured
87 | if (config.displayConfig & DisplayRight) {
88 | uint16_t value2 = sensor2Distance;
89 | String loc2 = sensor2Location;
90 | this->prepareTextOnGrid(3, 0, loc2);
91 | if (value2 == MAX_SENSOR_VALUE || value2 == 0) {
92 | this->prepareTextOnGrid(2, 1, "---", LARGE_FONT, 5, 0);
93 | } else {
94 | this->prepareTextOnGrid(2, 1,
95 | ObsUtils::to3DigitString(value2), LARGE_FONT, 5, 0);
96 | }
97 | }
98 | } // NOT SIMPLE
99 | if (config.displayConfig & DisplayDistanceDetail) {
100 | const int bufSize = 64;
101 | char buffer[bufSize];
102 | // #ifdef NERD_SENSOR_DISTANCE
103 | snprintf(buffer, bufSize - 1, "%03d|%02d|%03d", sensor1RawDistance,
104 | lastMeasurements, sensor2RawDistance);
105 | // #endif
106 | #ifdef NERD_HEAP
107 | snprintf(buffer, bufSize - 1, "%03d|%02d|%uk", sensor1RawDistance,
108 | lastMeasurements, ESP.getFreeHeap() / 1024);
109 | #endif
110 | #ifdef NERD_VOLT
111 | snprintf(buffer, bufSize - 1, "%03d|%02d|%3.2fV", sensor1RawDistance,
112 | lastMeasurements, voltageMeter->read());
113 | #endif
114 | #ifdef NERD_GPS
115 | snprintf(buffer, bufSize - 1, "%02ds|%s|%03u",
116 | satellites,
117 | gps.getHdopAsString().c_str(), gps.getLastNoiseLevel() );
118 | #endif
119 | this->prepareTextOnGrid(0, 4, buffer, MEDIUM_FONT);
120 | } else if (config.displayConfig & DisplayNumConfirmed) {
121 | showNumButtonPressed();
122 | showNumConfirmed();
123 | } else {
124 | // Show GPS info, when DisplaySatellites is configured
125 | if (config.displayConfig & DisplaySatellites) {
126 | showGPS(satellites);
127 | }
128 |
129 | // Show velocity, when DisplayVelocity is configured
130 | if (config.displayConfig & DisplayVelocity) {
131 | showSpeed(speed);
132 | }
133 | }
134 | if (batteryPercentage >= -1) {
135 | showBatterieValue(batteryPercentage);
136 | }
137 | if (!(config.displayConfig & DisplaySimple)){
138 | if(BMP280_active == true)
139 | showTemperatureValue(TemperaturValue);
140 | }
141 |
142 | m_display->updateDisplay();
143 |
144 | }
145 |
146 | void DisplayDevice::showGPS(uint8_t sats) {
147 | String val = String(sats);
148 | if (sats <= 9) {
149 | val = "0" + val;
150 | }
151 | this->prepareTextOnGrid(2, 4, val, MEDIUM_FONT);
152 | this->prepareTextOnGrid(3, 5, "sats");
153 | }
154 |
155 | void DisplayDevice::showBatterieValue(int16_t input_val){
156 |
157 | uint8_t x_offset_batterie_logo = 65;
158 | uint8_t y_offset_batterie_logo = 2;
159 | int8_t xlocation = 2;
160 |
161 | if ((config.displayConfig & DisplaySimple)){
162 | x_offset_batterie_logo += 32;
163 | xlocation += 1;
164 | }
165 |
166 | if(input_val >= 0){
167 | String val = String(input_val);
168 | //showLogo(true);
169 | this->showTextOnGrid(xlocation, 0, val + "%", TINY_FONT, 6, 0);
170 |
171 | if(input_val > 90){
172 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
173 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo1);
174 | }else if (input_val > 70)
175 | {
176 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
177 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo2);
178 | }else if (input_val> 50)
179 | {
180 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
181 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo3);
182 | }else if (input_val > 30)
183 | {
184 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
185 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo4);
186 | }else if (input_val >10)
187 | {
188 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
189 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo5);
190 | }else
191 | {
192 | cleanBattery(x_offset_batterie_logo, y_offset_batterie_logo);
193 | m_display->drawXBM(x_offset_batterie_logo, y_offset_batterie_logo, 8, 9, BatterieLogo6);
194 | }
195 |
196 | }
197 | }
198 |
199 | void DisplayDevice::showTemperatureValue(int16_t input_val){
200 | uint8_t x_offset_temp_logo = 30;
201 | uint8_t y_offset_temp_logo = 2;
202 | cleanTemperatur(x_offset_temp_logo,y_offset_temp_logo);
203 | m_display->drawXBM(x_offset_temp_logo, y_offset_temp_logo, 8, 9, TempLogo);
204 | String val = String(input_val);
205 | this->showTextOnGrid(1, 0, val + "°C", TINY_FONT);
206 | }
207 |
208 | void DisplayDevice::showSpeed(double velocity) {
209 | const int bufSize = 4;
210 | char buffer[bufSize];
211 | if (velocity >= 0) {
212 | snprintf(buffer, bufSize - 1, "%02d", (int) velocity);
213 | } else {
214 | snprintf(buffer, bufSize - 1, "--");
215 | }
216 | this->prepareTextOnGrid(0, 4, buffer, MEDIUM_FONT);
217 | this->prepareTextOnGrid(1, 5, "km/h");
218 | }
219 |
220 | uint8_t DisplayDevice::currentLine() const {
221 | return mCurrentLine;
222 | }
223 |
224 | uint8_t DisplayDevice::newLine() {
225 | if (mCurrentLine >= 5) {
226 | scrollUp();
227 | }
228 | return ++mCurrentLine;
229 | }
230 |
231 | uint8_t DisplayDevice::scrollUp() {
232 | for (uint8_t i = 0; i < 5; i++) {
233 | prepareTextOnGrid(2, i, obsDisplay->get_gridTextofCell(2, i + 1));
234 | }
235 | m_display->updateDisplay();
236 | return mCurrentLine--;
237 | }
238 |
239 | uint8_t DisplayDevice::startLine() {
240 | return mCurrentLine = 0;
241 | }
242 |
243 | void DisplayDevice::highlight(uint32_t highlightTimeMillis) {
244 | mHighlightTill = millis() + highlightTimeMillis;
245 | if (!mHighlighted) {
246 | setInversion(!mInverted);
247 | mHighlighted = true;
248 | }
249 | }
250 |
251 | void DisplayDevice::handleHighlight() {
252 | if (mHighlighted && mHighlightTill < millis()) {
253 | setInversion(mInverted);
254 | mHighlighted = false;
255 | }
256 | }
257 |
--------------------------------------------------------------------------------