commit
569da23b6b
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
src/loraconf.h
|
||||
src/ota.conf
|
70
README.md
70
README.md
@ -32,7 +32,7 @@ This can all be done with a single small and cheap ESP32 board for less than $20
|
||||
- WeMos: LoLin32 + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora),
|
||||
LoLin32lite + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora)
|
||||
|
||||
*SPI only*: (coming soon)
|
||||
*SPI only*: (code yet to come)
|
||||
|
||||
- Pyom: WiPy
|
||||
- WeMos: LoLin32, LoLin32 Lite, WeMos D32
|
||||
@ -47,7 +47,7 @@ Depending on board hardware following features are supported:
|
||||
- GPS
|
||||
|
||||
Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).<br>
|
||||
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory.<br>
|
||||
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory. If you want to use a ESP32 board which is not yet supported, use hal file generic.h and tailor pin mappings to your needs. Pull requests for new boards welcome.<br>
|
||||
|
||||
<b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thingiverse, see
|
||||
<A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A>, <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, <A HREF="https://www.thingiverse.com/thing:3005574">TTGOv2.1</A>, <A HREF="https://www.thingiverse.com/thing:3041339">T-BEAM</A> for example.<br>
|
||||
@ -62,6 +62,8 @@ Before compiling the code,
|
||||
|
||||
- **create file loraconf.h in your local /src directory** using the template [loraconf.sample.h](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/loraconf.sample.h) and populate it with your personal APPEUI und APPKEY for the LoRaWAN network. If you're using popular <A HREF="https://thethingsnetwork.org">TheThingsNetwork</A> you can copy&paste the keys from TTN console or output of ttnctl.
|
||||
|
||||
- **create file ota.conf in your local /src directory** using the template [ota.sample.conf](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/ota.sample.conf) and enter your WIFI network&key. These settings are used for downloading updates. If you want to push own OTA updates you need a <A HREF="https://bintray.com/JFrog">Bintray account</A>. Enter your Bintray user account data in ota.conf. If you don't need wireless firmware updates just rename ota.sample.conf to ota.conf.
|
||||
|
||||
To join the network only method OTAA is supported, not ABP. The DEVEUI for OTAA will be derived from the device's MAC adress during device startup and is shown as well on the device's display (if it has one) as on the serial console for copying it to your LoRaWAN network server settings.
|
||||
|
||||
If your device has a fixed DEVEUI enter this in your local loraconf.h file. During compile time this DEVEUI will be grabbed from loraconf.h and inserted in the code.
|
||||
@ -74,10 +76,14 @@ Use <A HREF="https://platformio.org/">PlatformIO</A> with your preferred IDE for
|
||||
|
||||
# Uploading
|
||||
|
||||
To upload the code to your ESP32 board this needs to be switched from run to bootloader mode. Boards with USB bridge like Heltec and TTGO usually have an onboard logic which allows soft switching by the upload tool. In PlatformIO this happenes automatically.<p>
|
||||
- **Initially, using USB/UART cable:**
|
||||
To upload the code via cable to your ESP32 board this needs to be switched from run to bootloader mode. Boards with USB bridge like Heltec and TTGO usually have an onboard logic which allows soft switching by the upload tool. In PlatformIO this happenes automatically.<p>
|
||||
The LoPy/LoPy4/FiPy board needs to be set manually. See these
|
||||
<A HREF="https://www.thethingsnetwork.org/labs/story/program-your-lopy-from-the-arduino-ide-using-lmic">instructions</A> how to do it. Don't forget to press on board reset button after switching between run and bootloader mode.<p>
|
||||
The original Pycom firmware is not needed, so there is no need to update it before flashing Paxcounter. Just flash the compiled paxcounter binary (.elf file) on your LoPy/LoPy4/FiPy. If you later want to go back to the Pycom firmware, download the firmware from Pycom and flash it over.
|
||||
|
||||
- **During runtime, using FOTA via WIFI:**
|
||||
After the ESP32 board is initially flashed and has joined a LoRaWAN network, the firmware can update itself by FOTA. This process is kicked off by sending a remote control command (see below) via LoRaWAN to the board. The board then tries to connect via WIFI to a cloud service (JFrog Bintray), checks for update, and if available downloads the binary and reboots with it. If something goes wrong during this process, the board reboots back to the current version. Prerequisites for FOTA are: 1. You own a Bintray repository, 2. you pushed the update binary to the Bintray repository, 3. internet access via encrypted (WPA2) WIFI is present at the board's site, 4. WIFI credentials were set in ota.conf and initially flashed to the board. Step 2 runs automated, just enter the credentials in ota.conf and set `upload_protocol = custom` in platformio.ini. Then press build and lean back watching platformio doing build and upload.
|
||||
|
||||
# Legal note
|
||||
|
||||
@ -128,7 +134,13 @@ If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you
|
||||
|
||||
To track a paxcounter device with on board GPS and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. The formats *plain* and *packed* generate the fields `latitude`, `longitude` and `hdop` required by ttnmapper.
|
||||
|
||||
Hereafter described is the default *plain* format, which uses MSB bit numbering.
|
||||
Hereafter described is the default *plain* format, which uses MSB bit numbering. Under /TTN in this repository you find some ready-to-go decoders which you may copy to your TTN console:
|
||||
|
||||
[**plain_decoder.js**](src/TTN/plain_decoder.js) |
|
||||
[**plain_converter.js**](src/TTN/plain_converter.js) |
|
||||
[**packed_decoder.js**](src/TTN/packed_decoder.js) |
|
||||
[**packed_converter.js**](src/TTN/packed_converter.js)
|
||||
|
||||
|
||||
**Port #1:** Paxcount data
|
||||
|
||||
@ -142,6 +154,7 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering.
|
||||
byte 3-10: Uptime [seconds]
|
||||
byte 11: CPU temperature [°C]
|
||||
bytes 12-15: Free RAM [bytes]
|
||||
bytes 16-17: Last CPU reset reason [core 0, core 1]
|
||||
|
||||
**Port #3:** Device configuration query result
|
||||
|
||||
@ -181,55 +194,11 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering.
|
||||
byte 1: Beacon RSSI reception level
|
||||
byte 2: Beacon identifier (0..255)
|
||||
|
||||
|
||||
[**plain_decoder.js**](src/TTN/plain_decoder.js)
|
||||
|
||||
```javascript
|
||||
function Decoder(bytes, port) {
|
||||
var decoded = {};
|
||||
|
||||
if (port === 1) {
|
||||
var i = 0;
|
||||
decoded.wifi = (bytes[i++] << 8) | bytes[i++];
|
||||
decoded.ble = (bytes[i++] << 8) | bytes[i++];
|
||||
if (bytes.length > 4) {
|
||||
decoded.latitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] );
|
||||
decoded.longitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] );
|
||||
decoded.sats = ( bytes[i++] );
|
||||
decoded.hdop = ( bytes[i++] << 8) | (bytes[i++] );
|
||||
decoded.altitude = ( bytes[i++] << 8) | (bytes[i++] );
|
||||
}
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
```
|
||||
|
||||
[**plain_converter.js**](src/TTN/plain_converter.js)
|
||||
|
||||
```javascript
|
||||
function Converter(decoded, port) {
|
||||
|
||||
var converted = decoded;
|
||||
|
||||
if (port === 1) {
|
||||
converted.pax = converted.ble + converted.wifi;
|
||||
if (converted.hdop) {
|
||||
converted.hdop /= 100;
|
||||
converted.latitude /= 1000000;
|
||||
converted.longitude /= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
```
|
||||
|
||||
# Remote control
|
||||
|
||||
The device listenes for remote control commands on LoRaWAN Port 2. Multiple commands per downlink are possible by concatenating them.
|
||||
|
||||
Note: all settings are stored in NVRAM and will be reloaded when device starts. To reset device to factory settings send remote command 09 02 09 00 unconfirmed(!) once.
|
||||
Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
|
||||
0x01 set scan RSSI limit
|
||||
|
||||
@ -272,12 +241,13 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
|
||||
useful to clear pending commands from LoRaWAN server quere, or to check RSSI on device
|
||||
|
||||
0x09 reset functions
|
||||
0x09 reset functions (send this command with confirmed ack only to avoid boot loops!)
|
||||
|
||||
0 = restart device
|
||||
1 = reset MAC counter to zero
|
||||
2 = reset device to factory settings
|
||||
3 = flush send queues
|
||||
9 = reboot device to OTA update via Wifi mode
|
||||
|
||||
0x0A set LoRaWAN payload send cycle
|
||||
|
||||
|
94
build.py
Normal file
94
build.py
Normal file
@ -0,0 +1,94 @@
|
||||
# build.py
|
||||
# pre-build script, setting up build environment
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import requests
|
||||
from os.path import basename
|
||||
from platformio import util
|
||||
|
||||
Import("env")
|
||||
|
||||
# get platformio environment variables
|
||||
project_config = util.load_project_config()
|
||||
|
||||
# check if file loraconf.h is present in source directory
|
||||
keyfile = str(env.get("PROJECTSRC_DIR")) + "/loraconf.h"
|
||||
if os.path.isfile(keyfile) and os.access(keyfile, os.R_OK):
|
||||
print "Parsing LORAWAN keys from " + keyfile
|
||||
else:
|
||||
sys.exit("Missing file loraconf.h, please create it using template loraconf.sample.h! Aborting.")
|
||||
|
||||
# check if file ota.conf is present in source directory
|
||||
keyfile = str(env.get("PROJECTSRC_DIR")) + "/" + project_config.get("common", "keyfile")
|
||||
if os.path.isfile(keyfile) and os.access(keyfile, os.R_OK):
|
||||
print "Parsing OTA keys from " + keyfile
|
||||
else:
|
||||
sys.exit("Missing file ota.conf, please create it using template ota.sample.conf! Aborting.")
|
||||
|
||||
# parse file ota.conf
|
||||
mykeys = {}
|
||||
with open(keyfile) as myfile:
|
||||
for line in myfile:
|
||||
key, value = line.partition("=")[::2]
|
||||
mykeys[key.strip()] = str(value).strip()
|
||||
|
||||
# get bintray user credentials
|
||||
user = mykeys["BINTRAY_USER"]
|
||||
repository = mykeys["BINTRAY_REPO"]
|
||||
apitoken = mykeys["BINTRAY_API_TOKEN"]
|
||||
|
||||
# get bintray upload parameters
|
||||
version = project_config.get("common", "release_version")
|
||||
package = str(env.get("PIOENV"))
|
||||
|
||||
# put bintray user credentials to platformio environment
|
||||
env.Replace(BINTRAY_USER=user)
|
||||
env.Replace(BINTRAY_REPO=repository)
|
||||
env.Replace(BINTRAY_API_TOKEN=apitoken)
|
||||
|
||||
# get runtime credentials and put them to compiler directive
|
||||
env.Replace(CPPDEFINES=[
|
||||
('WIFI_SSID', '\\"' + mykeys["OTA_WIFI_SSID"] + '\\"'),
|
||||
('WIFI_PASS', '\\"' + mykeys["OTA_WIFI_PASS"] + '\\"'),
|
||||
('BINTRAY_USER', '\\"' + mykeys["BINTRAY_USER"] + '\\"'),
|
||||
('BINTRAY_REPO', '\\"' + mykeys["BINTRAY_REPO"] + '\\"'),
|
||||
])
|
||||
|
||||
# function for pushing new firmware to bintray storage using API
|
||||
def publish_bintray(source, target, env):
|
||||
firmware_path = str(source[0])
|
||||
firmware_name = basename(firmware_path)
|
||||
url = "/".join([
|
||||
"https://api.bintray.com", "content",
|
||||
user, repository, package, version, firmware_name
|
||||
])
|
||||
|
||||
print("Uploading {0} to Bintray. Version: {1}".format(
|
||||
firmware_name, version))
|
||||
print(url)
|
||||
|
||||
headers = {
|
||||
"Content-type": "application/octet-stream",
|
||||
"X-Bintray-Publish": "1",
|
||||
"X-Bintray-Override": "1"
|
||||
}
|
||||
|
||||
r = requests.put(
|
||||
url,
|
||||
data=open(firmware_path, "rb"),
|
||||
headers=headers,
|
||||
auth=(user, apitoken))
|
||||
|
||||
if r.status_code != 201:
|
||||
print("Failed to submit package: {0}\n{1}".format(
|
||||
r.status_code, r.text))
|
||||
else:
|
||||
print("The firmware has been successfuly published at Bintray.com!")
|
||||
|
||||
# put build file name and upload command to platformio environment
|
||||
env.Replace(
|
||||
PROGNAME="firmware_" + package + "_v%s" % version,
|
||||
UPLOADCMD=publish_bintray
|
||||
)
|
24
lib/BintrayClient/library.json
Normal file
24
lib/BintrayClient/library.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "BintrayClient",
|
||||
"keywords": "bintray, ota, cdn, storage",
|
||||
"description": "A BintrayClient to connect to a JFrog Bintray.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "PlatformIO",
|
||||
"url": "https://platformio.org/"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/platformio/platformio-examples"
|
||||
},
|
||||
"export": {
|
||||
"include": "bintray-secure-ota/lib/BintrayClient"
|
||||
},
|
||||
"dependencies": {
|
||||
"ArduinoJson": "^5.13.1"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32"
|
||||
}
|
105
lib/BintrayClient/src/BintrayCertificates.h
Normal file
105
lib/BintrayClient/src/BintrayCertificates.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Parts of this file
|
||||
Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
**/
|
||||
|
||||
#ifndef BINTRAY_CERTIFICATES_H
|
||||
#define BINTRAY_CERTIFICATES_H
|
||||
|
||||
const char* BINTRAY_API_ROOT_CA = \
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
|
||||
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
||||
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
|
||||
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
|
||||
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
|
||||
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
|
||||
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
|
||||
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
|
||||
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
|
||||
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
|
||||
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
|
||||
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
|
||||
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
|
||||
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
|
||||
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
|
||||
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
|
||||
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const char* BINTRAY_AKAMAI_ROOT_CA = \
|
||||
"-----BEGIN CERTIFICATE-----\n"\
|
||||
"MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh\n"\
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"\
|
||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"\
|
||||
"QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJBgNVBAYTAlVT\n"\
|
||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIg\n"\
|
||||
"U2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"\
|
||||
"ANyuWJBNwcQwFZA1W248ghX1LFy949v/cUP6ZCWA1O4Yok3wZtAKc24RmDYXZK83\n"\
|
||||
"nf36QYSvx6+M/hpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yrBvSqXUu3R0bd\n"\
|
||||
"KpPDkC55gIDvEwRqFDu1m5K+wgdlTvza/P96rtxcflUxDOg5B6TXvi/TC2rSsd9f\n"\
|
||||
"/ld0Uzs1gN2ujkSYs58O09rg1/RrKatEp0tYhG2SS4HD2nOLEpdIkARFdRrdNzGX\n"\
|
||||
"kujNVA075ME/OV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6+guqw9ypzAO+sf0\n"\
|
||||
"/RR3w6RbKFfCs/mC/bdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8C\n"\
|
||||
"AQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY\n"\
|
||||
"aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6\n"\
|
||||
"Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwN6A1\n"\
|
||||
"oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RD\n"\
|
||||
"QS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v\n"\
|
||||
"d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA+AYRyCMWHVLyjnjUY4tCzh\n"\
|
||||
"xtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0GCSqGSIb3DQEB\n"\
|
||||
"CwUAA4IBAQAjPt9L0jFCpbZ+QlwaRMxp0Wi0XUvgBCFsS+JtzLHgl4+mUwnNqipl\n"\
|
||||
"5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq/sELfeNqzqPlt/yGFUzZgTHbO7Djc1lGA\n"\
|
||||
"8MXW5dRNJ2Srm8c+cftIl7gzbckTB+6WohsYFfZcTEDts8Ls/3HB40f/1LkAtDdC\n"\
|
||||
"2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8ZDOo0rwAhaPit\n"\
|
||||
"c+LJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4d60tbvVS3bR0\n"\
|
||||
"j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLz\n"\
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
const char* CLOUDFRONT_API_ROOT_CA = \
|
||||
"-----BEGIN CERTIFICATE-----\n"\
|
||||
"MIIE3zCCA8egAwIBAgIQYxgNOPuAl3ip0DWjFhj4QDANBgkqhkiG9w0BAQsFADCB\n"\
|
||||
"yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n"\
|
||||
"ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n"\
|
||||
"U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n"\
|
||||
"ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n"\
|
||||
"aG9yaXR5IC0gRzUwHhcNMTcxMTA2MDAwMDAwWhcNMjIxMTA1MjM1OTU5WjBhMQsw\n"\
|
||||
"CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu\n"\
|
||||
"ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjCC\n"\
|
||||
"ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALs3zTTce2vJsmiQrUp1/0a6\n"\
|
||||
"IQoIjfUZVMn7iNvzrvI6iZE8euarBhprz6wt6F4JJES6Ypp+1qOofuBUdSAFrFC3\n"\
|
||||
"nGMabDDc2h8Zsdce3v3X4MuUgzeu7B9DTt17LNK9LqUv5Km4rTrUmaS2JembawBg\n"\
|
||||
"kmD/TyFJGPdnkKthBpyP8rrptOmSMmu181foXRvNjB2rlQSVSfM1LZbjSW3dd+P7\n"\
|
||||
"SUu0rFUHqY+Vs7Qju0xtRfD2qbKVMLT9TFWMJ0pXFHyCnc1zktMWSgYMjFDRjx4J\n"\
|
||||
"vheh5iHK/YPlELyDpQrEZyj2cxQUPUZ2w4cUiSE0Ta8PRQymSaG6u5zFsTODKYUC\n"\
|
||||
"AwEAAaOCAScwggEjMB0GA1UdDgQWBBROIlQgGJXm427mD/r6uRLtBhePOTAPBgNV\n"\
|
||||
"HRMBAf8EBTADAQH/MF8GA1UdIARYMFYwVAYEVR0gADBMMCMGCCsGAQUFBwIBFhdo\n"\
|
||||
"dHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEFBQcCAjAZDBdodHRwczovL2Qu\n"\
|
||||
"c3ltY2IuY29tL3JwYTAvBgNVHR8EKDAmMCSgIqAghh5odHRwOi8vcy5zeW1jYi5j\n"\
|
||||
"b20vcGNhMy1nNS5jcmwwDgYDVR0PAQH/BAQDAgGGMC4GCCsGAQUFBwEBBCIwIDAe\n"\
|
||||
"BggrBgEFBQcwAYYSaHR0cDovL3Muc3ltY2QuY29tMB8GA1UdIwQYMBaAFH/TZafC\n"\
|
||||
"3ey78DAJ80M5+gKvMzEzMA0GCSqGSIb3DQEBCwUAA4IBAQBQ3dNWKSUBip6n5X1N\n"\
|
||||
"ua8bjKLSJzXlnescavPECMpFBlIIKH2mc6mL2Xr/wkSIBDrsqAO3sBcmoJN+n8V3\n"\
|
||||
"0O5JelrtEAFYSyRDXfu78ZlHn6kvV5/jPUFECEM/hdN0x8WdLpGjJMqfs0EG5qHj\n"\
|
||||
"+UaxpucWD445wea4zlK7hUR+MA8fq0Yd1HEKj4c8TcgaQIHMa4KHr448cQ69e3CP\n"\
|
||||
"ECRhRNg+RAKT2I7SlaVzLvaB/8yym2oMCEsoqiRT8dbXg35aKEYmmzn3O/mnB7bG\n"\
|
||||
"Ud/EUrkIf7FVamgYZd1fSzQeg1cHqf0ja6eHpvq2bTl+cWFHaq/84KlHe5Rh0Csm\n"\
|
||||
"pZzn\n"\
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
#endif // BINTRAY_CERTIFICATES_H
|
150
lib/BintrayClient/src/BintrayClient.cpp
Normal file
150
lib/BintrayClient/src/BintrayClient.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
Parts of this file
|
||||
Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
**/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include "BintrayClient.h"
|
||||
#include "BintrayCertificates.h"
|
||||
|
||||
BintrayClient::BintrayClient(const String &user, const String &repository, const String &package)
|
||||
: m_user(user), m_repo(repository), m_package(package),
|
||||
m_storage_host("dl.bintray.com"),
|
||||
m_api_host("api.bintray.com")
|
||||
{
|
||||
m_certificates.emplace_back("cloudfront.net", CLOUDFRONT_API_ROOT_CA);
|
||||
m_certificates.emplace_back("akamai.bintray.com", BINTRAY_AKAMAI_ROOT_CA);
|
||||
m_certificates.emplace_back("bintray.com", BINTRAY_API_ROOT_CA);
|
||||
}
|
||||
|
||||
String BintrayClient::getUser() const
|
||||
{
|
||||
return m_user;
|
||||
}
|
||||
|
||||
String BintrayClient::getRepository() const
|
||||
{
|
||||
return m_repo;
|
||||
}
|
||||
|
||||
String BintrayClient::getPackage() const
|
||||
{
|
||||
return m_package;
|
||||
}
|
||||
|
||||
String BintrayClient::getStorageHost() const
|
||||
{
|
||||
return m_storage_host;
|
||||
}
|
||||
|
||||
String BintrayClient::getApiHost() const
|
||||
{
|
||||
return m_api_host;
|
||||
}
|
||||
|
||||
String BintrayClient::getLatestVersionRequestUrl() const
|
||||
{
|
||||
return String("https://") + getApiHost() + "/packages/" + getUser() + "/" + getRepository() + "/" + getPackage() + "/versions/_latest";
|
||||
}
|
||||
|
||||
String BintrayClient::getBinaryRequestUrl(const String &version) const
|
||||
{
|
||||
return String("https://") + getApiHost() + "/packages/" + getUser() + "/" + getRepository() + "/" + getPackage() + "/versions/" + version + "/files";
|
||||
}
|
||||
|
||||
const char *BintrayClient::getCertificate(const String &url) const
|
||||
{
|
||||
for(auto& cert: m_certificates) {
|
||||
if(url.indexOf(cert.first) >= 0) {
|
||||
return cert.second;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the certificate for *.bintray.com by default
|
||||
return m_certificates.rbegin()->second;
|
||||
}
|
||||
|
||||
String BintrayClient::requestHTTPContent(const String &url) const
|
||||
{
|
||||
String payload;
|
||||
HTTPClient http;
|
||||
http.begin(url, getCertificate(url));
|
||||
int httpCode = http.GET();
|
||||
|
||||
if (httpCode > 0)
|
||||
{
|
||||
if (httpCode == HTTP_CODE_OK)
|
||||
{
|
||||
payload = http.getString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "GET request failed, error: %s", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
return payload;
|
||||
}
|
||||
|
||||
String BintrayClient::getLatestVersion() const
|
||||
{
|
||||
String version;
|
||||
const String url = getLatestVersionRequestUrl();
|
||||
String jsonResult = requestHTTPContent(url);
|
||||
const size_t bufferSize = 1024;
|
||||
if (jsonResult.length() > bufferSize)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: Firmware version data invalid.");
|
||||
return version;
|
||||
}
|
||||
StaticJsonBuffer<bufferSize> jsonBuffer;
|
||||
|
||||
JsonObject &root = jsonBuffer.parseObject(jsonResult.c_str());
|
||||
// Check for errors in parsing
|
||||
if (!root.success())
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: Firmware version data not found.");
|
||||
return version;
|
||||
}
|
||||
return root.get<String>("name");
|
||||
}
|
||||
|
||||
String BintrayClient::getBinaryPath(const String &version) const
|
||||
{
|
||||
String path;
|
||||
const String url = getBinaryRequestUrl(version);
|
||||
String jsonResult = requestHTTPContent(url);
|
||||
|
||||
const size_t bufferSize = 1024;
|
||||
if (jsonResult.length() > bufferSize)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: Firmware download path data invalid.");
|
||||
return path;
|
||||
}
|
||||
StaticJsonBuffer<bufferSize> jsonBuffer;
|
||||
|
||||
JsonArray &root = jsonBuffer.parseArray(jsonResult.c_str());
|
||||
JsonObject &firstItem = root[0];
|
||||
if (!root.success())
|
||||
{ //Check for errors in parsing
|
||||
ESP_LOGE(TAG, "Error: Firmware download path not found.");
|
||||
return path;
|
||||
}
|
||||
return "/" + getUser() + "/" + getRepository() + "/" + firstItem.get<String>("path");
|
||||
}
|
50
lib/BintrayClient/src/BintrayClient.h
Normal file
50
lib/BintrayClient/src/BintrayClient.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Parts of this file
|
||||
Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
**/
|
||||
|
||||
#ifndef BINTRAY_CLIENT_H
|
||||
#define BINTRAY_CLIENT_H
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <WString.h>
|
||||
|
||||
class BintrayClient {
|
||||
|
||||
public:
|
||||
BintrayClient(const String& user, const String& repository, const String& package);
|
||||
String getUser() const;
|
||||
String getRepository() const;
|
||||
String getPackage() const;
|
||||
String getStorageHost() const;
|
||||
String getApiHost() const;
|
||||
const char* getCertificate(const String& url) const;
|
||||
String getLatestVersion() const;
|
||||
String getBinaryPath(const String& version) const;
|
||||
|
||||
private:
|
||||
String requestHTTPContent(const String& url) const;
|
||||
String getLatestVersionRequestUrl() const;
|
||||
String getBinaryRequestUrl(const String& version) const;
|
||||
String m_user;
|
||||
String m_repo;
|
||||
String m_package;
|
||||
const String m_storage_host;
|
||||
const String m_api_host;
|
||||
std::vector<std::pair<String, const char*>> m_certificates;
|
||||
};
|
||||
|
||||
#endif // BINTRAY_CLIENT_H
|
@ -790,8 +790,12 @@ void radio_irq_handler (u1_t dio) {
|
||||
// now read the FIFO
|
||||
readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
|
||||
// read rx quality parameters
|
||||
LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
|
||||
LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
|
||||
//LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
|
||||
LMIC.snr = ((s1_t)readReg(LORARegPktSnrValue)) / 4;
|
||||
//LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
|
||||
LMIC.rssi = readReg(LORARegPktRssiValue) - 157; // RFI_HF for 868 and 915MHZ band
|
||||
if (LMIC.snr < 0)
|
||||
LMIC.rssi += LMIC.snr;
|
||||
} else if( flags & IRQ_LORA_RXTOUT_MASK ) {
|
||||
// indicate timeout
|
||||
LMIC.dataLen = 0;
|
||||
|
256
platformio.ini
256
platformio.ini
@ -1,10 +1,5 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/page/projectconf.html
|
||||
|
||||
@ -16,7 +11,8 @@ env_default = generic
|
||||
;env_default = heltec
|
||||
;env_default = ttgov1
|
||||
;env_default = ttgov2
|
||||
;env_default = ttgov21
|
||||
;env_default = ttgov21old
|
||||
;env_default = ttgov21new
|
||||
;env_default = ttgobeam
|
||||
;env_default = lopy
|
||||
;env_default = lopy4
|
||||
@ -24,14 +20,26 @@ env_default = generic
|
||||
;env_default = lolin32litelora
|
||||
;env_default = lolin32lora
|
||||
;env_default = lolin32lite
|
||||
;env_default = ebox, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new
|
||||
;
|
||||
description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around.
|
||||
|
||||
[common_env_data]
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 1.4.35
|
||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||
debug_level = 0
|
||||
; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA
|
||||
upload_protocol = esptool
|
||||
;upload_protocol = custom
|
||||
extra_scripts = pre:build.py
|
||||
keyfile = ota.conf
|
||||
platform_espressif32 = espressif32@1.3.0
|
||||
;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage
|
||||
board_build.partitions = no_ota.csv
|
||||
lib_deps_all =
|
||||
board_build.partitions = min_spiffs.csv
|
||||
monitor_speed = 115200
|
||||
lib_deps_all =
|
||||
ArduinoJson@^5.13.1
|
||||
lib_deps_display =
|
||||
U8g2@>=2.23.16
|
||||
lib_deps_rgbled =
|
||||
@ -39,199 +47,227 @@ lib_deps_rgbled =
|
||||
lib_deps_gps =
|
||||
TinyGPSPlus@>=1.0.2
|
||||
Time@>=1.5
|
||||
build_flags =
|
||||
; ---> NOTE: For production run set DEBUG_LEVEL level to NONE! <---
|
||||
; otherwise device may leak RAM
|
||||
;
|
||||
; None
|
||||
-DCORE_DEBUG_LEVEL=0
|
||||
; Error
|
||||
; -DCORE_DEBUG_LEVEL=1
|
||||
; Warn
|
||||
; -DCORE_DEBUG_LEVEL=2
|
||||
; Info
|
||||
; -DCORE_DEBUG_LEVEL=3
|
||||
; Debug
|
||||
; -DCORE_DEBUG_LEVEL=4
|
||||
; Verbose
|
||||
; -DCORE_DEBUG_LEVEL=5
|
||||
;
|
||||
build_flags =
|
||||
; override lora settings from LMiC library in lmic/config.h and use main.h instead
|
||||
-D_lmic_config_h_
|
||||
-include "src/paxcounter.conf"
|
||||
-include "src/hal/${PIOENV}.h"
|
||||
-w
|
||||
|
||||
'-DCORE_DEBUG_LEVEL=${common.debug_level}'
|
||||
'-DBINTRAY_PACKAGE="${PIOENV}"'
|
||||
'-DPROGVERSION="${common.release_version}"'
|
||||
|
||||
[env:ebox]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 115200
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common.lib_deps_all}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:heltec]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = heltec_wifi_lora_32
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 115200
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_display}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:ttgov1]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 115200
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_display}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:ttgov2]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_display}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:ttgov21]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
[env:ttgov21old]
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_display}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:ttgov21new]
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
lib_deps =
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:ttgobeam]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_gps}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_gps}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
-mfix-esp32-psram-cache-issue
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:fipy]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:lopy]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common_env_data.lib_deps_gps}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
${common.lib_deps_gps}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:lopy4]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common_env_data.lib_deps_gps}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
${common.lib_deps_gps}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
-mfix-esp32-psram-cache-issue
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:lolin32litelora]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = lolin32
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:lolin32lora]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = lolin32
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:lolin32lite]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = lolin32
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
|
||||
[env:generic]
|
||||
platform = ${common_env_data.platform_espressif32}
|
||||
platform = ${common.platform_espressif32}
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
board_build.partitions = ${common_env_data.board_build.partitions}
|
||||
board_build.partitions = ${common.board_build.partitions}
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps_all}
|
||||
${common_env_data.lib_deps_rgbled}
|
||||
${common_env_data.lib_deps_gps}
|
||||
${common_env_data.lib_deps_display}
|
||||
${common.lib_deps_all}
|
||||
${common.lib_deps_rgbled}
|
||||
${common.lib_deps_gps}
|
||||
${common.lib_deps_display}
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
${common.build_flags}
|
||||
upload_protocol = ${common.upload_protocol}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
monitor_speed = ${common.monitor_speed}
|
@ -18,13 +18,12 @@ function Decoder(bytes, port) {
|
||||
|
||||
if (port === 2) {
|
||||
// device status data
|
||||
return decode(bytes, [uint16, uptime, uint8, uint32], ['voltage', 'uptime', 'cputemp', 'memory']);
|
||||
return decode(bytes, [uint16, uptime, uint8, uint32, uint8, uint8], ['voltage', 'uptime', 'cputemp', 'memory', 'reset0', 'reset1']);
|
||||
}
|
||||
|
||||
|
||||
if (port === 3) {
|
||||
// device config data
|
||||
return decode(bytes, [uint8, uint8, uint16, uint8, uint8, uint8, uint8, bitmap], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']);
|
||||
return decode(bytes, [uint8, uint8, uint16, uint8, uint8, uint8, uint8, bitmap, version], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'version']);
|
||||
}
|
||||
|
||||
if (port === 4) {
|
||||
@ -56,6 +55,14 @@ var bytesToInt = function (bytes) {
|
||||
return i;
|
||||
};
|
||||
|
||||
var version = function (bytes) {
|
||||
if (bytes.length !== version.BYTES) {
|
||||
throw new Error('version must have exactly 10 bytes');
|
||||
}
|
||||
return String.fromCharCode.apply(null, bytes).split('\u0000')[0];
|
||||
};
|
||||
version.BYTES = 10;
|
||||
|
||||
var uint8 = function (bytes) {
|
||||
if (bytes.length !== uint8.BYTES) {
|
||||
throw new Error('uint8 must have exactly 1 byte');
|
||||
@ -186,6 +193,7 @@ if (typeof module === 'object' && typeof module.exports !== 'undefined') {
|
||||
latLng: latLng,
|
||||
hdop: hdop,
|
||||
bitmap: bitmap,
|
||||
version: version,
|
||||
decode: decode
|
||||
};
|
||||
}
|
@ -25,6 +25,9 @@ function Decoder(bytes, port) {
|
||||
decoded.uptime = ((bytes[i++] << 56) | (bytes[i++] << 48) | (bytes[i++] << 40) | (bytes[i++] << 32) |
|
||||
(bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]);
|
||||
decoded.temp = bytes[i++];
|
||||
decoded.memory = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]);
|
||||
decoded.reset0 = bytes[i++];
|
||||
decoded.reset1 = bytes[i++];
|
||||
}
|
||||
|
||||
if (port === 5) {
|
||||
|
@ -31,6 +31,7 @@ void defaultConfig() {
|
||||
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
|
||||
cfg.gpsmode = 1; // 0=disabled, 1=enabled
|
||||
cfg.monitormode = 0; // 0=disabled, 1=enabled
|
||||
cfg.runmode = 0; // 0=normal, 1=update
|
||||
|
||||
strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1);
|
||||
}
|
||||
@ -143,6 +144,10 @@ void saveConfig() {
|
||||
flash8 != cfg.monitormode)
|
||||
nvs_set_i8(my_handle, "monitormode", cfg.monitormode);
|
||||
|
||||
if (nvs_get_i8(my_handle, "runmode", &flash8) != ESP_OK ||
|
||||
flash8 != cfg.runmode)
|
||||
nvs_set_i8(my_handle, "runmode", cfg.runmode);
|
||||
|
||||
if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK ||
|
||||
flash16 != cfg.rssilimit)
|
||||
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
|
||||
@ -326,6 +331,14 @@ void loadConfig() {
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if (nvs_get_i8(my_handle, "runmode", &flash8) == ESP_OK) {
|
||||
cfg.runmode = flash8;
|
||||
ESP_LOGI(TAG, "Run mode = %d", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Run mode set to default %d", cfg.runmode);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
nvs_close(my_handle);
|
||||
ESP_LOGI(TAG, "Done");
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
// Basic config
|
||||
#include "globals.h"
|
||||
#include "senddata.h"
|
||||
#include "OTA.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
@ -14,6 +15,10 @@ void doHomework() {
|
||||
// update uptime counter
|
||||
uptime();
|
||||
|
||||
// check if update mode trigger switch was set
|
||||
if (cfg.runmode == 1)
|
||||
ESP.restart();
|
||||
|
||||
// read battery voltage into global variable
|
||||
#ifdef HAS_BATTERY_PROBE
|
||||
batt_voltage = read_voltage();
|
||||
|
@ -36,14 +36,14 @@ void init_display(const char *Productname, const char *Version) {
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(1500);
|
||||
vTaskDelay(1500 / portTICK_PERIOD_MS);
|
||||
u8x8.clear();
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(1500);
|
||||
vTaskDelay(1500 / portTICK_PERIOD_MS);
|
||||
|
||||
u8x8.setFlipMode(0);
|
||||
u8x8.clear();
|
||||
@ -74,7 +74,7 @@ void init_display(const char *Productname, const char *Version) {
|
||||
DisplayKey(buf, 8, true);
|
||||
#endif // HAS_LORA
|
||||
|
||||
delay(5000);
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
u8x8.clear();
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
|
||||
u8x8.draw2x2String(0, 0, "PAX:0");
|
||||
|
@ -4,10 +4,6 @@
|
||||
// The mother of all embedded development...
|
||||
#include <Arduino.h>
|
||||
|
||||
// attn: increment version after modifications to configData_t truct!
|
||||
#define PROGVERSION "1.4.23" // use max 10 chars here!
|
||||
#define PROGNAME "PAXCNT"
|
||||
|
||||
// std::set for unified array functions
|
||||
#include <set>
|
||||
#include <array>
|
||||
@ -31,6 +27,7 @@ typedef struct {
|
||||
uint8_t rgblum; // RGB Led luminosity (0..100%)
|
||||
uint8_t gpsmode; // 0=disabled, 1=enabled
|
||||
uint8_t monitormode; // 0=disabled, 1=enabled
|
||||
uint8_t runmode; // 0=normal, 1=update
|
||||
char version[10]; // Firmware version
|
||||
} configData_t;
|
||||
|
||||
@ -42,7 +39,7 @@ typedef struct {
|
||||
} MessageBuffer_t;
|
||||
|
||||
// global variables
|
||||
extern configData_t cfg; // current device configuration
|
||||
extern configData_t cfg; // current device configuration
|
||||
extern char display_line6[], display_line7[]; // screen buffers
|
||||
extern uint8_t channel; // wifi channel rotation counter
|
||||
extern uint16_t macs_total, macs_wifi, macs_ble, batt_voltage; // display values
|
||||
@ -51,7 +48,8 @@ extern hw_timer_t *channelSwitch, *sendCycle;
|
||||
extern portMUX_TYPE timerMux;
|
||||
extern volatile int SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ,
|
||||
ChannelTimerIRQ, ButtonPressedIRQ;
|
||||
extern QueueHandle_t LoraSendQueue, SPISendQueue;
|
||||
// extern QueueHandle_t LoraSendQueue, SPISendQueue;
|
||||
extern TaskHandle_t WifiLoopTask;
|
||||
|
||||
extern std::array<uint64_t, 0xff>::iterator it;
|
||||
extern std::array<uint64_t, 0xff> beacons;
|
||||
@ -67,9 +65,15 @@ extern std::array<uint64_t, 0xff> beacons;
|
||||
#include "payload.h"
|
||||
|
||||
#ifdef HAS_LORA
|
||||
extern QueueHandle_t LoraSendQueue;
|
||||
extern TaskHandle_t LoraTask;
|
||||
#include "lorawan.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SPI
|
||||
extern QueueHandle_t SPISendQueue;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
#include "display.h"
|
||||
#endif
|
||||
|
@ -42,7 +42,7 @@ void gps_loop(void *pvParameters) {
|
||||
while (GPS_Serial.available()) {
|
||||
gps.encode(GPS_Serial.read());
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS); // reset watchdog
|
||||
}
|
||||
// after GPS function was disabled, close connect to GPS device
|
||||
GPS_Serial.end();
|
||||
@ -58,7 +58,7 @@ void gps_loop(void *pvParameters) {
|
||||
Wire.requestFrom(GPS_ADDR | 0x01, 32);
|
||||
while (Wire.available()) {
|
||||
gps.encode(Wire.read());
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS); // polling mode: 500ms sleep
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS); // polling mode: 500ms sleep
|
||||
}
|
||||
}
|
||||
// after GPS function was disabled, close connect to GPS device
|
||||
@ -67,7 +67,7 @@ void gps_loop(void *pvParameters) {
|
||||
#endif // GPS Type
|
||||
}
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS); // reset watchdog
|
||||
|
||||
} // end of infinite loop
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
/* Hardware related definitions for TTGO V2.1 Board
|
||||
/ ATTENTION: check your board version!
|
||||
/ Different versions are on the market which need different settings in this file:
|
||||
/ - without label -> use settings (2)
|
||||
/ - labeled V1.5 on pcb -> use settings (2)
|
||||
/ - labeled V1.6 on pcb -> use settings (1)
|
||||
/ Choose the right configuration below
|
||||
*/
|
||||
|
||||
/*
|
||||
// (1) settings for board labeled "T3_V1.6" on pcb
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_LED GPIO_NUM_25 // green on board LED
|
||||
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
||||
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
|
||||
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
|
||||
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST GPIO_NUM_23 // ESP32 GPIO23 <-> HPD13A RESET
|
||||
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0
|
||||
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
|
||||
#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
|
||||
|
||||
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
|
||||
#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN
|
||||
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2
|
||||
#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0
|
||||
|
||||
*/
|
||||
|
||||
// (2) settings for boards without label on pcb, or labeled v1.5 on pcb
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
#define HAS_LED NOT_A_PIN // no usable LED on board
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define DISPLAY_FLIP 1 // rotated display
|
||||
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
||||
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
|
||||
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
|
||||
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board)
|
||||
//#define RST GPIO_NUM_12 // (boards labeled v1.5)
|
||||
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0
|
||||
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
|
||||
#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
|
||||
|
||||
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
|
||||
#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN
|
||||
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2
|
||||
#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0
|
30
src/hal/ttgov21new.h
Normal file
30
src/hal/ttgov21new.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* Hardware related definitions for TTGO V2.1 Board
|
||||
// ATTENTION: check your board version!
|
||||
// This settings are for boards labeled v1.6 on pcb, NOT for v1.5 or older
|
||||
*/
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_LED GPIO_NUM_25 // green on board LED
|
||||
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
||||
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
|
||||
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
|
||||
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST GPIO_NUM_23 // ESP32 GPIO23 <-> HPD13A RESET
|
||||
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0
|
||||
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
|
||||
#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
|
||||
|
||||
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
|
||||
#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN
|
||||
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2
|
||||
#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0
|
32
src/hal/ttgov21old.h
Normal file
32
src/hal/ttgov21old.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* Hardware related definitions for TTGO V2.1 Board
|
||||
// ATTENTION: check your board version!
|
||||
// This settings are for boards without label on pcb, or labeled v1.5 on pcb
|
||||
*/
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
#define HAS_LED NOT_A_PIN // no usable LED on board
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define DISPLAY_FLIP 1 // rotated display
|
||||
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
||||
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
|
||||
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
|
||||
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board)
|
||||
//#define RST GPIO_NUM_12 // (boards labeled v1.5)
|
||||
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0
|
||||
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
|
||||
#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
|
||||
|
||||
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
|
||||
#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN
|
||||
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2
|
||||
#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0
|
@ -196,11 +196,9 @@ void onEvent(ev_t ev) {
|
||||
|
||||
if (LMIC.dataLen) {
|
||||
ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d",
|
||||
LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4);
|
||||
// LMIC.snr = SNR twos compliment [dB] * 4
|
||||
// LMIC.rssi = RSSI [dBm] (-196...+63)
|
||||
LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr);
|
||||
sprintf(display_line6, "RSSI %d SNR %d", LMIC.rssi,
|
||||
(signed char)LMIC.snr / 4);
|
||||
(signed char)LMIC.snr);
|
||||
|
||||
// check if command is received on command port, then call interpreter
|
||||
if ((LMIC.txrxFlags & TXRX_PORT) &&
|
||||
@ -229,7 +227,7 @@ void lorawan_loop(void *pvParameters) {
|
||||
|
||||
while (1) {
|
||||
os_runloop_once(); // execute LMIC jobs
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS); // reset watchdog
|
||||
}
|
||||
}
|
||||
|
||||
|
36
src/main.cpp
36
src/main.cpp
@ -24,7 +24,6 @@ licenses. Refer to LICENSE.txt file in repository for more details.
|
||||
*/
|
||||
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
#include "main.h"
|
||||
|
||||
configData_t cfg; // struct holds current device configuration
|
||||
@ -41,9 +40,12 @@ hw_timer_t *channelSwitch = NULL, *displaytimer = NULL, *sendCycle = NULL,
|
||||
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0,
|
||||
DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
|
||||
|
||||
TaskHandle_t WifiLoopTask = NULL;
|
||||
|
||||
// RTos send queues for payload transmit
|
||||
#ifdef HAS_LORA
|
||||
QueueHandle_t LoraSendQueue;
|
||||
TaskHandle_t LoraTask = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SPI
|
||||
@ -67,6 +69,9 @@ static const char TAG[] = "main";
|
||||
|
||||
void setup() {
|
||||
|
||||
// disable the default wifi logging
|
||||
esp_log_level_set("wifi", ESP_LOG_NONE);
|
||||
|
||||
char features[100] = "";
|
||||
|
||||
// disable brownout detection
|
||||
@ -85,11 +90,12 @@ void setup() {
|
||||
esp_log_set_vprintf(redirect_log);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting %s v%s", PROGNAME, PROGVERSION);
|
||||
ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
|
||||
|
||||
// initialize system event handler for wifi task, needed for
|
||||
// wifi_sniffer_init()
|
||||
esp_event_loop_init(NULL, NULL);
|
||||
// esp_event_loop_init(NULL, NULL);
|
||||
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
||||
|
||||
// print chip information on startup if in verbose mode
|
||||
#ifdef VERBOSE
|
||||
@ -115,6 +121,13 @@ void setup() {
|
||||
// read settings from NVRAM
|
||||
loadConfig(); // includes initialize if necessary
|
||||
|
||||
// reboot to firmware update mode if ota trigger switch is set
|
||||
if (cfg.runmode == 1) {
|
||||
cfg.runmode = 0;
|
||||
saveConfig();
|
||||
start_ota_update();
|
||||
}
|
||||
|
||||
#ifdef VENDORFILTER
|
||||
strcat_P(features, " OUIFLT");
|
||||
#endif
|
||||
@ -200,7 +213,7 @@ void setup() {
|
||||
#ifdef HAS_DISPLAY
|
||||
strcat_P(features, " OLED");
|
||||
DisplayState = cfg.screenon;
|
||||
init_display(PROGNAME, PROGVERSION);
|
||||
init_display(PRODUCTNAME, PROGVERSION);
|
||||
|
||||
// setup display refresh trigger IRQ using esp32 hardware timer
|
||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||
@ -269,7 +282,7 @@ void setup() {
|
||||
|
||||
ESP_LOGI(TAG, "Starting Lora task on core 1");
|
||||
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1,
|
||||
(5 | portPRIVILEGE_BIT), NULL, 1);
|
||||
(5 | portPRIVILEGE_BIT), &LoraTask, 1);
|
||||
#endif
|
||||
|
||||
// if device has GPS and it is enabled, start GPS reader task on core 0 with
|
||||
@ -294,11 +307,11 @@ void setup() {
|
||||
ESP_LOGI(TAG, "Starting Wifi task on core 0");
|
||||
wifi_sniffer_init();
|
||||
// initialize salt value using esp_random() called by random() in
|
||||
// arduino-esp32 core. Note: do this *after* wifi has started, since function
|
||||
// gets it's seed from RF noise
|
||||
// arduino-esp32 core. Note: do this *after* wifi has started, since
|
||||
// function gets it's seed from RF noise
|
||||
reset_salt(); // get new 16bit for salting hashes
|
||||
xTaskCreatePinnedToCore(wifi_channel_loop, "wifiloop", 2048, (void *)1, 1,
|
||||
NULL, 0);
|
||||
&WifiLoopTask, 0);
|
||||
} // setup()
|
||||
|
||||
/* end Arduino SETUP
|
||||
@ -310,7 +323,8 @@ void setup() {
|
||||
void loop() {
|
||||
|
||||
while (1) {
|
||||
// state machine for switching display, LED, button, housekeeping, senddata
|
||||
// state machine for switching display, LED, button, housekeeping,
|
||||
// senddata
|
||||
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
led_loop();
|
||||
@ -330,8 +344,8 @@ void loop() {
|
||||
processSendBuffer();
|
||||
// check send cycle and enqueue payload if cycle is expired
|
||||
sendPayload();
|
||||
// reset watchdog
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
// reset watchdog
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||
|
||||
} // loop()
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
#ifndef _MAIN_H
|
||||
#define _MAIN_H
|
||||
|
||||
//#include "led.h"
|
||||
#include "globals.h"
|
||||
#include "led.h"
|
||||
#include "macsniff.h"
|
||||
#include "wifiscan.h"
|
||||
#include "configmanager.h"
|
||||
#include "senddata.h"
|
||||
#include "cyclic.h"
|
||||
#include "beacon_array.h"
|
||||
#include "OTA.h"
|
||||
|
||||
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
||||
#include <esp_event_loop.h> // needed for Wifi event handler
|
||||
|
275
src/ota.cpp
Normal file
275
src/ota.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
Parts of this code:
|
||||
Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "OTA.h"
|
||||
|
||||
const BintrayClient bintray(BINTRAY_USER, BINTRAY_REPO, BINTRAY_PACKAGE);
|
||||
|
||||
// Connection port (HTTPS)
|
||||
const int port = 443;
|
||||
|
||||
// Connection timeout
|
||||
const uint32_t RESPONSE_TIMEOUT_MS = 5000;
|
||||
|
||||
// Variables to validate firmware content
|
||||
volatile int contentLength = 0;
|
||||
volatile bool isValidContentType = false;
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
|
||||
void start_ota_update() {
|
||||
|
||||
ESP_LOGI(TAG, "Starting Wifi OTA update");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
|
||||
int i = WIFI_MAX_TRY;
|
||||
while (i--) {
|
||||
ESP_LOGI(TAG, "trying to connect to %s", WIFI_SSID);
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
break;
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
if (i >= 0) {
|
||||
ESP_LOGI(TAG, "connected to %s", WIFI_SSID);
|
||||
checkFirmwareUpdates(); // gets and flashes new firmware and restarts
|
||||
} else
|
||||
ESP_LOGI(TAG, "could not connect to %s, rebooting.", WIFI_SSID);
|
||||
|
||||
ESP.restart(); // reached only if update was not successful or no wifi connect
|
||||
|
||||
} // start_ota_update
|
||||
|
||||
void checkFirmwareUpdates() {
|
||||
// Fetch the latest firmware version
|
||||
ESP_LOGI(TAG, "OTA mode, checking latest firmware version on server...");
|
||||
const String latest = bintray.getLatestVersion();
|
||||
|
||||
if (latest.length() == 0) {
|
||||
ESP_LOGI(
|
||||
TAG,
|
||||
"Could not load info about the latest firmware. Rebooting to runmode.");
|
||||
return;
|
||||
} else if (version_compare(latest, cfg.version) <= 0) {
|
||||
ESP_LOGI(TAG, "Current firmware is up to date. Rebooting to runmode.");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "New firmware version v%s available. Downloading...",
|
||||
latest.c_str());
|
||||
processOTAUpdate(latest);
|
||||
}
|
||||
|
||||
// A helper function to extract header value from header
|
||||
inline String getHeaderValue(String header, String headerName) {
|
||||
return header.substring(strlen(headerName.c_str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* OTA update processing
|
||||
*/
|
||||
void processOTAUpdate(const String &version) {
|
||||
String firmwarePath = bintray.getBinaryPath(version);
|
||||
if (!firmwarePath.endsWith(".bin")) {
|
||||
ESP_LOGI(TAG, "Unsupported binary format, OTA update cancelled.");
|
||||
return;
|
||||
}
|
||||
|
||||
String currentHost = bintray.getStorageHost();
|
||||
String prevHost = currentHost;
|
||||
|
||||
WiFiClientSecure client;
|
||||
client.setCACert(bintray.getCertificate(currentHost));
|
||||
|
||||
if (!client.connect(currentHost.c_str(), port)) {
|
||||
ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
bool redirect = true;
|
||||
while (redirect) {
|
||||
if (currentHost != prevHost) {
|
||||
client.stop();
|
||||
client.setCACert(bintray.getCertificate(currentHost));
|
||||
if (!client.connect(currentHost.c_str(), port)) {
|
||||
ESP_LOGI(TAG, "Redirect detected, but cannot connect to %s",
|
||||
currentHost.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Requesting %s", firmwarePath.c_str());
|
||||
|
||||
client.print(String("GET ") + firmwarePath + " HTTP/1.1\r\n");
|
||||
client.print(String("Host: ") + currentHost + "\r\n");
|
||||
client.print("Cache-Control: no-cache\r\n");
|
||||
client.print("Connection: close\r\n\r\n");
|
||||
|
||||
unsigned long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > RESPONSE_TIMEOUT_MS) {
|
||||
ESP_LOGI(TAG, "Client Timeout.");
|
||||
client.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
// Check if the line is end of headers by removing space symbol
|
||||
line.trim();
|
||||
// if the the line is empty, this is the end of the headers
|
||||
if (!line.length()) {
|
||||
break; // proceed to OTA update
|
||||
}
|
||||
|
||||
// Check allowed HTTP responses
|
||||
if (line.startsWith("HTTP/1.1")) {
|
||||
if (line.indexOf("200") > 0) {
|
||||
ESP_LOGI(TAG, "Got 200 status code from server. Proceeding to "
|
||||
"firmware flashing");
|
||||
redirect = false;
|
||||
} else if (line.indexOf("302") > 0) {
|
||||
ESP_LOGI(TAG, "Got 302 status code from server. Redirecting to the "
|
||||
"new address");
|
||||
redirect = true;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Could not get a valid firmware url.");
|
||||
// Unexptected HTTP response. Retry or skip update?
|
||||
redirect = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Extracting new redirect location
|
||||
if (line.startsWith("Location: ")) {
|
||||
String newUrl = getHeaderValue(line, "Location: ");
|
||||
ESP_LOGI(TAG, "Got new url: %s", newUrl.c_str());
|
||||
newUrl.remove(0, newUrl.indexOf("//") + 2);
|
||||
currentHost = newUrl.substring(0, newUrl.indexOf('/'));
|
||||
newUrl.remove(newUrl.indexOf(currentHost), currentHost.length());
|
||||
firmwarePath = newUrl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Checking headers
|
||||
if (line.startsWith("Content-Length: ")) {
|
||||
contentLength =
|
||||
atoi((getHeaderValue(line, "Content-Length: ")).c_str());
|
||||
ESP_LOGI(TAG, "Got %d bytes from server", contentLength);
|
||||
}
|
||||
|
||||
if (line.startsWith("Content-Type: ")) {
|
||||
String contentType = getHeaderValue(line, "Content-Type: ");
|
||||
ESP_LOGI(TAG, "Got %s payload", contentType.c_str());
|
||||
if (contentType == "application/octet-stream") {
|
||||
isValidContentType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we have everything for OTA update
|
||||
if (contentLength && isValidContentType) {
|
||||
|
||||
size_t written;
|
||||
|
||||
if (Update.begin(contentLength)) {
|
||||
|
||||
int i = FLASH_MAX_TRY;
|
||||
while ((i--) && (written != contentLength)) {
|
||||
|
||||
ESP_LOGI(TAG,
|
||||
"Starting OTA update, attempt %d of %d. This will take some "
|
||||
"time to complete...",
|
||||
FLASH_MAX_TRY - i, FLASH_MAX_TRY);
|
||||
|
||||
written = Update.writeStream(client);
|
||||
|
||||
if (written == contentLength) {
|
||||
ESP_LOGI(TAG, "Written %d bytes successfully", written);
|
||||
break;
|
||||
} else {
|
||||
ESP_LOGI(TAG,
|
||||
"Written only %d of %d bytes, OTA update attempt cancelled.",
|
||||
written, contentLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (Update.end()) {
|
||||
|
||||
if (Update.isFinished()) {
|
||||
ESP_LOGI(
|
||||
TAG,
|
||||
"OTA update completed. Rebooting to runmode with new version.");
|
||||
client.stop();
|
||||
return;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Something went wrong! OTA update hasn't been finished "
|
||||
"properly.");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "An error occurred. Error #: %d", Update.getError());
|
||||
}
|
||||
|
||||
} else {
|
||||
ESP_LOGI(TAG, "There isn't enough space to start OTA update");
|
||||
client.flush();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG,
|
||||
"There was no valid content in the response from the OTA server!");
|
||||
client.flush();
|
||||
}
|
||||
ESP_LOGI(TAG,
|
||||
"OTA update failed. Rebooting to runmode with current version.");
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// helper function to compare two versions. Returns 1 if v2 is
|
||||
// smaller, -1 if v1 is smaller, 0 if equal
|
||||
|
||||
int version_compare(const String v1, const String v2) {
|
||||
// vnum stores each numeric part of version
|
||||
int vnum1 = 0, vnum2 = 0;
|
||||
|
||||
// loop untill both string are processed
|
||||
for (int i = 0, j = 0; (i < v1.length() || j < v2.length());) {
|
||||
// storing numeric part of version 1 in vnum1
|
||||
while (i < v1.length() && v1[i] != '.') {
|
||||
vnum1 = vnum1 * 10 + (v1[i] - '0');
|
||||
i++;
|
||||
}
|
||||
|
||||
// storing numeric part of version 2 in vnum2
|
||||
while (j < v2.length() && v2[j] != '.') {
|
||||
vnum2 = vnum2 * 10 + (v2[j] - '0');
|
||||
j++;
|
||||
}
|
||||
|
||||
if (vnum1 > vnum2)
|
||||
return 1;
|
||||
if (vnum2 > vnum1)
|
||||
return -1;
|
||||
|
||||
// if equal, reset variables and go for next numeric
|
||||
// part
|
||||
vnum1 = vnum2 = 0;
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
return 0;
|
||||
}
|
15
src/ota.h
Normal file
15
src/ota.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef OTA_H
|
||||
#define OTA_H
|
||||
|
||||
#include "globals.h"
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <Update.h>
|
||||
#include <BintrayClient.h>
|
||||
|
||||
void checkFirmwareUpdates();
|
||||
void processOTAUpdate(const String &version);
|
||||
void start_ota_update();
|
||||
int version_compare(const String v1, const String v2);
|
||||
|
||||
#endif // OTA_H
|
8
src/ota.sample.conf
Normal file
8
src/ota.sample.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[ota]
|
||||
OTA_WIFI_SSID = MyHomeWifi
|
||||
OTA_WIFI_PASS = FooBar42!
|
||||
|
||||
[bintray]
|
||||
BINTRAY_USER = MyBintrayUser
|
||||
BINTRAY_REPO = MyBintrayRepo
|
||||
BINTRAY_API_TOKEN = 3894a7a51d70c6523c1b7479261c34845ebf7878
|
@ -4,12 +4,14 @@
|
||||
//
|
||||
// Note: After editing, before "build", use "clean" button in PlatformIO!
|
||||
|
||||
#define PRODUCTNAME "PAXCNT"
|
||||
|
||||
// Verbose enables serial output
|
||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||
|
||||
// Payload send cycle and encoding
|
||||
#define SEND_SECS 30 // payload send cycle [seconds/2] -> 60 sec.
|
||||
#define PAYLOAD_ENCODER 1 // payload encoder: 1=Plain, 2=Packed, 3=CayenneLPP dynamic, 4=CayenneLPP packed
|
||||
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=CayenneLPP dynamic, 4=CayenneLPP packed
|
||||
|
||||
// Set this to include BLE counting and vendor filter functions
|
||||
#define VENDORFILTER 1 // comment out if you want to count things, not people
|
||||
@ -63,6 +65,10 @@
|
||||
#define DISPLAYREFRESH_MS 40 // OLED refresh cycle in ms [default = 40] -> 1000/40 = 25 frames per second
|
||||
#define HOMECYCLE 30 // house keeping cycle in seconds [default = 30 secs]
|
||||
|
||||
// OTA settings
|
||||
#define WIFI_MAX_TRY 20 // maximum number of wifi connect attempts for OTA update [default = 20]
|
||||
#define FLASH_MAX_TRY 3 // maximum number of attempts for writing update binary to flash [default = 3]
|
||||
|
||||
// LMIC settings
|
||||
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
|
||||
// define hardware specifics settings in platformio.ini as build_flag for hardware environment
|
||||
|
@ -52,8 +52,9 @@ void PayloadConvert::addConfig(configData_t value) {
|
||||
cursor += 10;
|
||||
}
|
||||
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
|
||||
float cputemp, uint32_t mem) {
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
|
||||
uint32_t mem, uint8_t reset1, uint8_t reset2) {
|
||||
|
||||
buffer[cursor++] = highByte(voltage);
|
||||
buffer[cursor++] = lowByte(voltage);
|
||||
buffer[cursor++] = (byte)((uptime & 0xFF00000000000000) >> 56);
|
||||
@ -69,6 +70,8 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
|
||||
buffer[cursor++] = (byte)((mem & 0x00FF0000) >> 16);
|
||||
buffer[cursor++] = (byte)((mem & 0x0000FF00) >> 8);
|
||||
buffer[cursor++] = (byte)((mem & 0x000000FF));
|
||||
buffer[cursor++] = (byte)(reset1);
|
||||
buffer[cursor++] = (byte)(reset2);
|
||||
}
|
||||
|
||||
#ifdef HAS_GPS
|
||||
@ -121,14 +124,17 @@ void PayloadConvert::addConfig(configData_t value) {
|
||||
value.screenon ? true : false, value.countermode ? true : false,
|
||||
value.blescan ? true : false, value.wifiant ? true : false,
|
||||
value.vendorfilter ? true : false, value.gpsmode ? true : false);
|
||||
writeVersion(value.version);
|
||||
}
|
||||
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
|
||||
float cputemp, uint32_t mem) {
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
|
||||
uint32_t mem, uint8_t reset1, uint8_t reset2) {
|
||||
writeUint16(voltage);
|
||||
writeUptime(uptime);
|
||||
writeUint8((byte)cputemp);
|
||||
writeUint32(mem);
|
||||
writeUint8(reset1);
|
||||
writeUint8(reset2);
|
||||
}
|
||||
|
||||
#ifdef HAS_GPS
|
||||
@ -155,6 +161,11 @@ void PayloadConvert::writeUptime(uint64_t uptime) {
|
||||
intToBytes(cursor, uptime, 8);
|
||||
}
|
||||
|
||||
void PayloadConvert::writeVersion(char * version) {
|
||||
memcpy(buffer + cursor, version, 10);
|
||||
cursor += 10;
|
||||
}
|
||||
|
||||
void PayloadConvert::writeLatLng(double latitude, double longitude) {
|
||||
intToBytes(cursor, latitude, 4);
|
||||
intToBytes(cursor, longitude, 4);
|
||||
@ -241,8 +252,8 @@ void PayloadConvert::addConfig(configData_t value) {
|
||||
buffer[cursor++] = value.adrmode;
|
||||
}
|
||||
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
|
||||
float celsius, uint32_t mem) {
|
||||
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float celsius,
|
||||
uint32_t mem, uint8_t reset1, uint8_t reset2) {
|
||||
uint16_t temp = celsius * 10;
|
||||
uint16_t volt = voltage / 10;
|
||||
#ifdef HAS_BATTERY_PROBE
|
||||
|
@ -35,7 +35,8 @@ public:
|
||||
uint8_t *getBuffer(void);
|
||||
void addCount(uint16_t value1, uint16_t value2);
|
||||
void addConfig(configData_t value);
|
||||
void addStatus(uint16_t voltage, uint64_t uptime, float cputemp, uint32_t mem);
|
||||
void addStatus(uint16_t voltage, uint64_t uptime, float cputemp, uint32_t mem,
|
||||
uint8_t reset1, uint8_t reset2);
|
||||
void addAlarm(int8_t rssi, uint8_t message);
|
||||
#ifdef HAS_GPS
|
||||
void addGPS(gpsStatus_t value);
|
||||
@ -44,7 +45,6 @@ public:
|
||||
void addButton(uint8_t value);
|
||||
#endif
|
||||
|
||||
|
||||
#if PAYLOAD_ENCODER == 1 // format plain
|
||||
|
||||
private:
|
||||
@ -64,6 +64,7 @@ private:
|
||||
void writeUint8(uint8_t i);
|
||||
void writeHumidity(float humidity);
|
||||
void writeTemperature(float temperature);
|
||||
void writeVersion(char * version);
|
||||
void writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, bool g,
|
||||
bool h);
|
||||
|
||||
@ -77,7 +78,6 @@ private:
|
||||
#else
|
||||
#error "No valid payload converter defined"
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
extern PayloadConvert payload;
|
||||
|
@ -31,6 +31,11 @@ void set_reset(uint8_t val[]) {
|
||||
sprintf(display_line6, "Queue reset");
|
||||
flushQueues();
|
||||
break;
|
||||
case 9: // reset and ask for software update via Wifi OTA
|
||||
ESP_LOGI(TAG, "Remote command: software update via Wifi");
|
||||
sprintf(display_line6, "Software update");
|
||||
cfg.runmode = 1;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Remote command: reset called with invalid parameter(s)");
|
||||
}
|
||||
@ -203,7 +208,8 @@ void get_status(uint8_t val[]) {
|
||||
#endif
|
||||
payload.reset();
|
||||
payload.addStatus(voltage, uptime() / 1000, temperatureRead(),
|
||||
ESP.getFreeHeap());
|
||||
ESP.getFreeHeap(), rtc_get_reset_reason(0),
|
||||
rtc_get_reset_reason(1));
|
||||
SendData(STATUSPORT);
|
||||
};
|
||||
|
||||
@ -221,14 +227,14 @@ void get_gps(uint8_t val[]) {
|
||||
|
||||
// assign previously defined functions to set of numeric remote commands
|
||||
// format: opcode, function, #bytes params,
|
||||
// flag (1 = do make settings persistent / 0 = don't)
|
||||
// flag (true = do make settings persistent / false = don't)
|
||||
//
|
||||
cmd_t table[] = {
|
||||
{0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true},
|
||||
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
|
||||
{0x05, set_lorasf, 1, true}, {0x06, set_lorapower, 1, true},
|
||||
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
|
||||
{0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true},
|
||||
{0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true},
|
||||
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},
|
||||
{0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true},
|
||||
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "configmanager.h"
|
||||
#include "lorawan.h"
|
||||
#include "macsniff.h"
|
||||
#include <rom/rtc.h>
|
||||
|
||||
// table of remote commands and assigned functions
|
||||
typedef struct {
|
||||
|
@ -6,7 +6,7 @@
|
||||
static const char TAG[] = "wifi";
|
||||
|
||||
static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN,
|
||||
WIFI_CHANNEL_MAX, 0,
|
||||
WIFI_CHANNEL_MAX, 100,
|
||||
WIFI_COUNTRY_POLICY_MANUAL};
|
||||
|
||||
// using IRAM_:ATTR here to speed up callback function
|
||||
@ -36,6 +36,7 @@ void wifi_sniffer_init(void) {
|
||||
ESP_ERROR_CHECK(
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
|
||||
ESP_ERROR_CHECK(esp_wifi_stop());
|
||||
ESP_ERROR_CHECK(
|
||||
esp_wifi_set_promiscuous_filter(&filter)); // set MAC frame filter
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler));
|
||||
@ -58,7 +59,7 @@ void wifi_channel_loop(void *pvParameters) {
|
||||
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
||||
ESP_LOGD(TAG, "Wifi set channel %d", channel);
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS); // reset watchdog
|
||||
}
|
||||
|
||||
} // end of infinite wifi channel rotation loop
|
||||
|
Loading…
Reference in New Issue
Block a user