Merge branch 'ota-test' into development
This commit is contained in:
		
						commit
						8999c77579
					
				
							
								
								
									
										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" | ||||
| } | ||||
							
								
								
									
										102
									
								
								lib/BintrayClient/src/BintrayCertificates.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								lib/BintrayClient/src/BintrayCertificates.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| /*
 | ||||
|  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" \ | ||||
| "MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n" \ | ||||
| "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\n" \ | ||||
| "YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG\n" \ | ||||
| "EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg\n" \ | ||||
| "R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9\n" \ | ||||
| "9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq\n" \ | ||||
| "fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv\n" \ | ||||
| "iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU\n" \ | ||||
| "1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+\n" \ | ||||
| "bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW\n" \ | ||||
| "MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA\n" \ | ||||
| "ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l\n" \ | ||||
| "uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn\n" \ | ||||
| "Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS\n" \ | ||||
| "tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF\n" \ | ||||
| "PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un\n" \ | ||||
| "hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV\n" \ | ||||
| "5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==\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
 | ||||
							
								
								
									
										149
									
								
								lib/BintrayClient/src/BintrayClient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								lib/BintrayClient/src/BintrayClient.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | ||||
| /*
 | ||||
|  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 | ||||
|     { | ||||
|         Serial.printf("GET request failed, error: %s\n", 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_LOGI(TAG, "Error: Could not parse JSON. Input data is too big!"); | ||||
|         return version; | ||||
|     } | ||||
|     StaticJsonBuffer<bufferSize> jsonBuffer; | ||||
| 
 | ||||
|     JsonObject &root = jsonBuffer.parseObject(jsonResult.c_str()); | ||||
|     // Check for errors in parsing
 | ||||
|     if (!root.success()) | ||||
|     { | ||||
|         ESP_LOGI(TAG, "Error: Could not parse JSON!"); | ||||
|         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_LOGI(TAG, "Error: Could parse JSON. Input data is too big!"); | ||||
|         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_LOGI(TAG, "Error: Could not parse JSON!"); | ||||
|         return path; | ||||
|     } | ||||
|     return "/" + getUser() + "/" + getRepository() + "/" + firstItem.get<String>("path"); | ||||
| } | ||||
							
								
								
									
										49
									
								
								lib/BintrayClient/src/BintrayClient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lib/BintrayClient/src/BintrayClient.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| /*
 | ||||
|  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
 | ||||
| @ -11,12 +11,12 @@ | ||||
| 
 | ||||
| ; ---> SELECT TARGET PLATFORM HERE! <--- | ||||
| [platformio] | ||||
| env_default = generic | ||||
| ;env_default = generic | ||||
| ;env_default = ebox | ||||
| ;env_default = heltec | ||||
| ;env_default = ttgov1 | ||||
| ;env_default = ttgov2 | ||||
| ;env_default = ttgov21 | ||||
| env_default = ttgov21 | ||||
| ;env_default = ttgobeam | ||||
| ;env_default = lopy | ||||
| ;env_default = lopy4 | ||||
| @ -27,11 +27,55 @@ env_default = generic | ||||
| ; | ||||
| description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. | ||||
| 
 | ||||
| [bintray] | ||||
| user = cyberman54 | ||||
| repository = paxcounter | ||||
| package = esp32-paxcounter | ||||
| api_token = *** | ||||
| 
 | ||||
| [wifi] | ||||
| ssid = *** | ||||
| password = *** | ||||
| 
 | ||||
| [common] | ||||
| platform = https://github.com/platformio/platform-espressif32.git | ||||
| 
 | ||||
| ; firmware version, please modify it between releases | ||||
| ; positive integer value | ||||
| release_version = 4 | ||||
| 
 | ||||
| ; build configuration based on Bintray and Wi-Fi settings | ||||
| build_flags = | ||||
|     '-DWIFI_SSID="${wifi.ssid}"' | ||||
|     '-DWIFI_PASS="${wifi.password}"' | ||||
|     '-DBINTRAY_USER="${bintray.user}"' | ||||
|     '-DBINTRAY_REPO="${bintray.repository}"' | ||||
|     '-DBINTRAY_PACKAGE="${bintray.package}"' | ||||
|     -DVERSION=${common.release_version} | ||||
| ; | ||||
| ; ---> 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 | ||||
| 
 | ||||
| [common_env_data] | ||||
| 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 = no_ota.csv | ||||
| board_build.partitions = min_spiffs.csv | ||||
| lib_deps_all =  | ||||
|     ArduinoJson | ||||
| lib_deps_display = | ||||
|     U8g2@>=2.23.16 | ||||
| lib_deps_rgbled = | ||||
| @ -40,28 +84,12 @@ 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 | ||||
| ; | ||||
| ; 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 | ||||
|   | ||||
| 
 | ||||
| [env:ebox] | ||||
| platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| @ -124,6 +152,7 @@ lib_deps = | ||||
|     ${common_env_data.lib_deps_all} | ||||
|     ${common_env_data.lib_deps_display} | ||||
| build_flags =  | ||||
|     ${common.build_flags} | ||||
|     ${common_env_data.build_flags} | ||||
| 
 | ||||
| [env:ttgobeam] | ||||
|  | ||||
							
								
								
									
										79
									
								
								src/OTA.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/OTA.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| #include "OTA.h" | ||||
| 
 | ||||
| const BintrayClient bintray(BINTRAY_USER, BINTRAY_REPO, BINTRAY_PACKAGE); | ||||
| 
 | ||||
| bool Wifi_Connected = false; | ||||
| 
 | ||||
| esp_err_t event_handler(void *ctx, system_event_t *event) { | ||||
|   switch (event->event_id) { | ||||
|   case SYSTEM_EVENT_STA_START: | ||||
|     esp_wifi_connect(); | ||||
|     ESP_LOGI(TAG, "Event STA_START"); | ||||
|     break; | ||||
|   case SYSTEM_EVENT_STA_GOT_IP: | ||||
|     Wifi_Connected = true; | ||||
|     ESP_LOGI(TAG, "Event STA_GOT_IP"); | ||||
|     // print the local IP address
 | ||||
|     tcpip_adapter_ip_info_t ip_info; | ||||
|     ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info)); | ||||
|     ESP_LOGI(TAG, "IP %s", ip4addr_ntoa(&ip_info.ip)); | ||||
|     break; | ||||
|   case SYSTEM_EVENT_STA_DISCONNECTED: | ||||
|     Wifi_Connected = false; | ||||
|     ESP_LOGI(TAG, "Event STA_DISCONNECTED"); | ||||
|     break; | ||||
|   default: | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void ota_wifi_init(void) { | ||||
| 
 | ||||
|   tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_STA; | ||||
| 
 | ||||
|   // initialize the tcp stack
 | ||||
|   // nvs_flash_init();
 | ||||
|   tcpip_adapter_init(); | ||||
|   tcpip_adapter_set_hostname(tcpip_if, PROGNAME); | ||||
|   tcpip_adapter_dhcpc_start(tcpip_if); | ||||
| 
 | ||||
|   // initialize the wifi event handler
 | ||||
|   ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); | ||||
| 
 | ||||
|   // switch off monitor more
 | ||||
|   ESP_ERROR_CHECK( | ||||
|       esp_wifi_set_promiscuous(false)); // now switch on monitor mode
 | ||||
|   ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(NULL)); | ||||
| 
 | ||||
|   wifi_sta_config_t cfg; | ||||
|   strcpy((char *)cfg.ssid, WIFI_SSID); | ||||
|   strcpy((char *)cfg.password, WIFI_PASS); | ||||
|   cfg.bssid_set = false; | ||||
| 
 | ||||
|   wifi_config_t sta_cfg; | ||||
|   sta_cfg.sta = cfg; | ||||
| 
 | ||||
|   wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT(); | ||||
| 
 | ||||
|   ESP_ERROR_CHECK(esp_wifi_init(&wifi_cfg)); | ||||
|   ESP_ERROR_CHECK( | ||||
|       esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
 | ||||
|   ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); | ||||
|   ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_cfg)); | ||||
|   ESP_ERROR_CHECK(esp_wifi_start()); | ||||
| } | ||||
| 
 | ||||
| void start_ota_update() { | ||||
|   ESP_LOGI(TAG, "Stopping Wifi task on core 0"); | ||||
|   vTaskDelete(WifiLoopTask); | ||||
| 
 | ||||
|   ESP_LOGI(TAG, "Stopping LORA task on core 1"); | ||||
|   vTaskDelete(LoraTask); | ||||
| 
 | ||||
|   ESP_LOGI(TAG, "Connecting to %s", WIFI_SSID); | ||||
|   ota_wifi_init(); | ||||
|   delay(2000); | ||||
|   delay(2000); | ||||
|   checkFirmwareUpdates(); | ||||
|   ESP.restart(); // reached if update was not successful
 | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/OTA.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/OTA.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| #ifndef OTA_H | ||||
| #define OTA_H | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #include "globals.h" | ||||
| #include <BintrayClient.h> | ||||
| #include <WiFi.h> | ||||
| #include "ota.h" | ||||
| #include "SecureOTA.h" | ||||
| 
 | ||||
| void start_ota_update(); | ||||
| 
 | ||||
| #endif // OTA_H
 | ||||
							
								
								
									
										225
									
								
								src/SecureOTA.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								src/SecureOTA.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,225 @@ | ||||
| /*
 | ||||
|  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 <WiFiClientSecure.h> | ||||
| #include <Update.h> | ||||
| #include <BintrayClient.h> | ||||
| #include "SecureOTA.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; | ||||
| 
 | ||||
| void checkFirmwareUpdates() | ||||
| { | ||||
|   // Fetch the latest firmware version
 | ||||
|   const String latest = bintray.getLatestVersion(); | ||||
|   if (latest.length() == 0) | ||||
|   { | ||||
|     ESP_LOGI(TAG, "Could not load info about the latest firmware, so nothing to update. Continue ..."); | ||||
|     return; | ||||
|   } | ||||
|   else if (atoi(latest.c_str()) <= VERSION) | ||||
|   { | ||||
|     //ESP_LOGI(TAG, "The current firmware is up to date. Continue ...");
 | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   ESP_LOGI(TAG, "There is a new version of firmware available: v.%s", latest); | ||||
|   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 cannot be performed!"); | ||||
|     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); | ||||
|     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! Cannot connect to %s for some reason!", currentHost); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     //ESP_LOGI(TAG, "Requesting: " + firmwarePath);
 | ||||
| 
 | ||||
|     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); | ||||
|         newUrl.remove(0, newUrl.indexOf("//") + 2); | ||||
|         currentHost = newUrl.substring(0, newUrl.indexOf('/')); | ||||
|         newUrl.remove(newUrl.indexOf(currentHost), currentHost.length()); | ||||
|         firmwarePath = newUrl; | ||||
|         ESP_LOGI(TAG, "firmwarePath: %s", firmwarePath); | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       // Checking headers
 | ||||
|       if (line.startsWith("Content-Length: ")) | ||||
|       { | ||||
|         contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str()); | ||||
|         ESP_LOGI(TAG, "Got %s bytes from server", String(contentLength)); | ||||
|       } | ||||
| 
 | ||||
|       if (line.startsWith("Content-Type: ")) | ||||
|       { | ||||
|         String contentType = getHeaderValue(line, "Content-Type: "); | ||||
|         ESP_LOGI(TAG, "Got %s payload", contentType); | ||||
|         if (contentType == "application/octet-stream") | ||||
|         { | ||||
|           isValidContentType = true; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // check whether we have everything for OTA update
 | ||||
|   if (contentLength && isValidContentType) | ||||
|   { | ||||
|     if (Update.begin(contentLength)) | ||||
|     { | ||||
|       ESP_LOGI(TAG, "Starting Over-The-Air update. This may take some time to complete ..."); | ||||
|       size_t written = Update.writeStream(client); | ||||
| 
 | ||||
|       if (written == contentLength) | ||||
|       { | ||||
|         ESP_LOGI(TAG, "Written %s successfully", String(written)); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         ESP_LOGI(TAG, "Written only %s / %s Retry?", String(written), String(contentLength)); | ||||
|         // Retry??
 | ||||
|       } | ||||
| 
 | ||||
|       if (Update.end()) | ||||
|       { | ||||
|         if (Update.isFinished()) | ||||
|         { | ||||
|           ESP_LOGI(TAG, "OTA update has successfully completed. Rebooting ..."); | ||||
|           ESP.restart(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|           ESP_LOGI(TAG, "Something went wrong! OTA update hasn't been finished properly."); | ||||
|         } | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         ESP_LOGI(TAG, "An error occurred. Error #: %s", String(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(); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/SecureOTA.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/SecureOTA.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| /*
 | ||||
|  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 SECURE_OTA_H | ||||
| #define SECURE_OTA_H | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| 
 | ||||
| void checkFirmwareUpdates(); | ||||
| void processOTAUpdate(const String &version); | ||||
| 
 | ||||
| #endif // SECURE_OTA_H
 | ||||
| @ -21,7 +21,6 @@ function Decoder(bytes, port) { | ||||
|         return decode(bytes, [uint16, uptime, uint8, uint32], ['voltage', 'uptime', 'cputemp', 'memory']); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     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']); | ||||
| @ -181,6 +180,7 @@ if (typeof module === 'object' && typeof module.exports !== 'undefined') { | ||||
|         uint16: uint16, | ||||
|         uint32: uint32, | ||||
|         uptime: uptime, | ||||
|         reset: reset, | ||||
|         temperature: temperature, | ||||
|         humidity: humidity, | ||||
|         latLng: latLng, | ||||
|  | ||||
| @ -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,9 @@ void doHomework() { | ||||
|   // update uptime counter
 | ||||
|   uptime(); | ||||
| 
 | ||||
|   if (ota_update) | ||||
|     start_ota_update(); | ||||
| 
 | ||||
| // read battery voltage into global variable
 | ||||
| #ifdef HAS_BATTERY_PROBE | ||||
|   batt_voltage = read_voltage(); | ||||
|  | ||||
| @ -42,7 +42,8 @@ typedef struct { | ||||
| } MessageBuffer_t; | ||||
| 
 | ||||
| // global variables
 | ||||
| extern configData_t cfg;                      // current device configuration
 | ||||
| extern configData_t cfg; // current device configuration
 | ||||
| extern bool ota_update; | ||||
| 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 +52,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 +69,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 | ||||
|  | ||||
							
								
								
									
										18
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -27,7 +27,8 @@ licenses. Refer to LICENSE.txt file in repository for more details. | ||||
| #include "globals.h" | ||||
| #include "main.h" | ||||
| 
 | ||||
| configData_t cfg; // struct holds current device configuration
 | ||||
| configData_t cfg;        // struct holds current device configuration
 | ||||
| bool ota_update = false; // triggers OTA update
 | ||||
| char display_line6[16], display_line7[16]; // display buffers
 | ||||
| uint8_t channel = 0;                       // channel rotation counter
 | ||||
| uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0, | ||||
| @ -41,9 +42,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 +71,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
 | ||||
| @ -89,7 +96,8 @@ void setup() { | ||||
| 
 | ||||
|   // 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 | ||||
| @ -269,7 +277,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
 | ||||
| @ -298,7 +306,7 @@ void setup() { | ||||
|   // 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
 | ||||
| @ -330,7 +338,7 @@ void loop() { | ||||
|     processSendBuffer(); | ||||
|     // check send cycle and enqueue payload if cycle is expired
 | ||||
|     sendPayload(); | ||||
|     // reset watchdog	
 | ||||
|     // reset watchdog
 | ||||
|     vTaskDelay(1 / portTICK_PERIOD_MS); | ||||
| 
 | ||||
|   } // loop()
 | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| 
 | ||||
| // 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 | ||||
|  | ||||
| @ -54,6 +54,7 @@ void PayloadConvert::addConfig(configData_t value) { | ||||
| 
 | ||||
| void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, | ||||
|                                float cputemp, uint32_t mem) { | ||||
| 
 | ||||
|   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 | ||||
| @ -123,12 +126,14 @@ void PayloadConvert::addConfig(configData_t value) { | ||||
|               value.vendorfilter ? true : false, value.gpsmode ? true : false); | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| @ -241,8 +246,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: | ||||
| @ -77,7 +77,6 @@ private: | ||||
| #else | ||||
| #error "No valid payload converter defined" | ||||
| #endif | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| extern PayloadConvert payload; | ||||
|  | ||||
| @ -203,7 +203,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); | ||||
| }; | ||||
| 
 | ||||
| @ -219,6 +220,11 @@ void get_gps(uint8_t val[]) { | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| void set_update(uint8_t val[]) { | ||||
|   ESP_LOGI(TAG, "Remote command: get firmware update"); | ||||
|   ota_update = true; | ||||
| }; | ||||
| 
 | ||||
| // assign previously defined functions to set of numeric remote commands
 | ||||
| // format: opcode, function, #bytes params,
 | ||||
| // flag (1 = do make settings persistent / 0 = don't)
 | ||||
| @ -233,8 +239,8 @@ cmd_t table[] = { | ||||
|     {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, | ||||
|     {0x0f, set_wifiant, 1, true},       {0x10, set_rgblum, 1, true}, | ||||
|     {0x11, set_monitor, 1, true},       {0x12, set_beacon, 7, false}, | ||||
|     {0x80, get_config, 0, false},       {0x81, get_status, 0, false}, | ||||
|     {0x84, get_gps, 0, false}}; | ||||
|     {0x20, set_update, 0, false},       {0x80, get_config, 0, false}, | ||||
|     {0x81, get_status, 0, false},       {0x84, get_gps, 0, false}}; | ||||
| 
 | ||||
| const uint8_t cmdtablesize = | ||||
|     sizeof(table) / sizeof(table[0]); // number of commands in command table
 | ||||
|  | ||||
| @ -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)); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user