├── .gitignore ├── LICENSE ├── NukiClientESP.h ├── README.md ├── examples ├── Autodiscover │ └── Autodiscover.ino └── Static │ └── Static.ino ├── keywords.txt ├── library.json ├── library.properties └── src ├── NukiClientESP.cpp └── NukiClientESP.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # config file for testing examples 35 | testConfig.h -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 thexperiments 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NukiClientESP.h: -------------------------------------------------------------------------------- 1 | #include "src/NukiClientESP.h" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NukiClientESP 2 | Library for accessing the nuki smartlock with an ESP8266. 3 | 4 | Autodiscovery and authentication supported. 5 | 6 | Required libraries: 7 | * ArduinoJson 5.13.x 8 | * ESP8266 libraries (installed if you install the esp8266 board files) 9 | 10 | Tested with an nodeMCU 1.0 11 | 12 | Usage: 13 | * See Examples 14 | * * Autodiscovering the lock and authenticating with the bridge. 15 | * * Using a static configuration to operate a lock 16 | 17 | Todo: 18 | * Clean up 19 | * Reduce use of String to use less RAM 20 | * Support callbacks to update the lock state 21 | * Real world testing 22 | 23 | With some modification this should also work on other platforms. 24 | I am not affiliated with Nuki Home Solutions, this not an official library, NUKI is a trademark of Nuki Home Solutions. 25 | -------------------------------------------------------------------------------- /examples/Autodiscover/Autodiscover.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //ESP8266 wifi stuff 4 | #include 5 | #include 6 | ESP8266WiFiMulti WiFiMulti; 7 | 8 | //the nuki library for access to the smart lock bridge 9 | #include 10 | 11 | NukiClientESP nuki; 12 | 13 | //configuration 14 | //#define TEST_NUKI_CLIENT_ESP 15 | #ifndef TEST_NUKI_CLIENT_ESP 16 | const char * WIFI_SSID = "YourFancySSID"; 17 | const char * WIFI_PASSWORD = "YourCoolWifiPassword"; 18 | #else 19 | #include "testconfig.h" 20 | #endif 21 | 22 | //helpers 23 | void printHeap(){ 24 | Serial.printf("FreeHeap: %i\n", ESP.getFreeHeap()); 25 | } 26 | 27 | void setup() { 28 | // put your setup code here, to run once: 29 | Serial.begin(115200); 30 | WiFi.mode(WIFI_STA); 31 | WiFiMulti.addAP(WIFI_SSID, WIFI_PASSWORD); 32 | Serial.print("Wait for WiFi... "); 33 | while (WiFiMulti.run() != WL_CONNECTED) { 34 | Serial.print("."); 35 | delay(500); 36 | } 37 | Serial.println(""); 38 | Serial.println("WiFi connected"); 39 | Serial.println("IP address: "); 40 | Serial.println(WiFi.localIP()); 41 | 42 | //Set up lock 43 | std::vector bridgeIPs; 44 | std::vector bridgePorts; 45 | nuki.discoverBridges(bridgeIPs, bridgePorts); 46 | nuki.useBridge(bridgeIPs[0], bridgePorts[0]); 47 | String token; 48 | nuki.authenticateBridge(token); 49 | nuki.useBridgeAuthToken(token); 50 | std::vector lockIDs; 51 | nuki.discoverLocks(lockIDs); 52 | nuki.useLock(lockIDs[0]); 53 | // interact with lock 54 | nuki.getLockState(); 55 | nuki.unlock(); 56 | delay(5000); 57 | nuki.getLockState(); 58 | delay(5000); 59 | nuki.lock(); 60 | nuki.getLockState(); 61 | } 62 | 63 | void loop() { 64 | // put your main code here, to run repeatedly: 65 | } 66 | 67 | -------------------------------------------------------------------------------- /examples/Static/Static.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //ESP8266 wifi stuff 4 | #include 5 | #include 6 | ESP8266WiFiMulti WiFiMulti; 7 | 8 | //the nuki library for access to the smart lock bridge 9 | #include 10 | 11 | NukiClientESP nuki; 12 | 13 | //configuration 14 | //#define TEST_NUKI_CLIENT_ESP 15 | #ifndef TEST_NUKI_CLIENT_ESP 16 | const char * WIFI_SSID = "YourFancySSID"; 17 | const char * WIFI_PASSWORD = "YourCoolWifiPassword"; 18 | const char * BRIDGE_IP = "192.some.bridge.ip"; 19 | const int BRIDGE_PORT = 8080; 20 | const char * BRIDGE_TOKEN = "asdf12qwe342"; 21 | const int LOCK_ID = 123456789; 22 | #else 23 | #include "testconfig.h" 24 | #endif 25 | 26 | //helpers 27 | void printHeap(){ 28 | Serial.printf("FreeHeap: %i\n", ESP.getFreeHeap()); 29 | } 30 | 31 | void setup() { 32 | // put your setup code here, to run once: 33 | Serial.begin(115200); 34 | WiFi.mode(WIFI_STA); 35 | WiFiMulti.addAP(WIFI_SSID, WIFI_PASSWORD); 36 | Serial.print("Wait for WiFi... "); 37 | while (WiFiMulti.run() != WL_CONNECTED) { 38 | Serial.print("."); 39 | delay(500); 40 | } 41 | Serial.println(""); 42 | Serial.println("WiFi connected"); 43 | Serial.println("IP address: "); 44 | Serial.println(WiFi.localIP()); 45 | 46 | //Set up lock 47 | nuki.useBridge(BRIDGE_IP, BRIDGE_PORT); 48 | nuki.useBridgeAuthToken(BRIDGE_TOKEN); 49 | nuki.useLock(LOCK_ID); 50 | nuki.getLockState(); 51 | } 52 | 53 | void loop() { 54 | // put your main code here, to run repeatedly: 55 | 56 | delay(1000); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | NUKI_lock_states KEYWORD1 2 | state_uncalibrated LITERAL1 3 | state_locked LITERAL1 4 | state_unlocking LITERAL1 5 | state_unlocked LITERAL1 6 | state_locking LITERAL1 7 | state_unlatched LITERAL1 8 | state_unlocked_lockngo LITERAL1 9 | state_unlatching LITERAL1 10 | state_motor_blocked LITERAL1 11 | state_undefined LITERAL1 12 | 13 | NUKI_lock_actions KEYWORD1 14 | action_unlock LITERAL1 15 | action_lock LITERAL1 16 | action_unlatch LITERAL1 17 | action_lockngo LITERAL1 18 | action_lockngo_with_unlatch LITERAL1 19 | 20 | NUKI_http_responses KEYWORD1 21 | response_invalid_action LITERAL1 22 | response_invalid_token LITERAL1 23 | response_authentication_disabled LITERAL1 24 | response_samrtlock_unknown LITERAL1 25 | response_smartlock_offline LITERAL1 26 | 27 | NukiClientESP KEYWORD1 28 | 29 | ##################################################################################### 30 | ## Functions for setting up the Library 31 | ##################################################################################### 32 | discoverBridges KEYWORD2 33 | authenticateBridge KEYWORD2 34 | useBridge KEYWORD2 35 | useBridgeAuthToken KEYWORD2 36 | 37 | discoverLocks KEYWORD2 38 | useLock KEYWORD2 39 | 40 | ##################################################################################### 41 | ## Functions for controlling the lock 42 | ##################################################################################### 43 | triggerLockAction KEYWORD2 44 | lock KEYWORD2 45 | unlock KEYWORD2 46 | unlatch KEYWORD2 47 | 48 | ##################################################################################### 49 | ## Functions for getting the lock state 50 | ##################################################################################### 51 | getLockState KEYWORD2 52 | isLocked KEYWORD2 53 | getBridgeInfo KEYWORD2 54 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NukiClientESP", 3 | "keywords": "nuki, nuki.io, smarthome, smartlock", 4 | "description": "Library for accessing the nuki smartlock with an ESP8266. I am not affiliated with Nuki Home Solutions, this not an official library, NUKI is a trademark of Nuki Home Solutions.", 5 | "homepage": "https://github.com/thexperiments/NukiClientESP", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/thexperiments/NukiClientESP.git" 9 | }, 10 | "version": "0.0.1", 11 | "authors": { 12 | "name": "Lukas Reinhart", 13 | "url": "https://thexperiments.com" 14 | }, 15 | "frameworks": "arduino", 16 | "platforms": "*", 17 | "dependencies": 18 | [ 19 | { 20 | "name": "ArduinoJson", 21 | "version": "~5.13.4" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=NukiClientESP 2 | version=0.0.1 3 | author=Lukas Reinhart 4 | maintainer=Lukas Reinhart 5 | sentence=Library for accessing the nuki smartlock with an ESP8266 6 | paragraph=Library for accessing the nuki smartlock with an ESP8266. Autodiscovery and authentication supported. With some modification this should also work on other platforms. I am not affiliated with Nuki Home Solutions, this not an official library, NUKI is a trademark of Nuki Home Solutions. 7 | category=Device Control 8 | url=https://github.com/thexperiments/NukiClientESP 9 | architectures=* 10 | repository=https://github.com/thexperiments/NukiClientESP.git 11 | license=MIT -------------------------------------------------------------------------------- /src/NukiClientESP.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Library for accessing the NUKI bridge. 3 | Intended for use with ESP8266 but also should work with other boards 4 | */ 5 | #include "NukiClientESP.h" 6 | 7 | NukiClientESP::NukiClientESP(){ 8 | // set up the http timeout as the lock sometimes takes quite some time to respond 9 | _http.setTimeout(10000); //timout is in ms -> 10000 ms = 10 seconds 10 | } 11 | NukiClientESP::NukiClientESP(String bridgeIp, uint bridgePort){ 12 | NukiClientESP(); 13 | useBridge(bridgeIp, bridgePort); 14 | } 15 | NukiClientESP::NukiClientESP(String bridgeIp, uint bridgePort, String bridgeAuthToken){ 16 | useBridgeAuthToken(bridgeAuthToken); 17 | NukiClientESP(bridgeIp,bridgePort); 18 | } 19 | NukiClientESP::NukiClientESP(String bridgeIp, uint bridgePort, String bridgeAuthToken, uint lockID){ 20 | useLock(lockID); 21 | NukiClientESP(bridgeIp,bridgePort, bridgeAuthToken); 22 | } 23 | 24 | bool NukiClientESP::discoverBridges(std::vector &bridgeIPs, std::vector &bridgePorts){ 25 | String responseString; 26 | StaticJsonBuffer<1024> jsonBuffer; 27 | 28 | Serial.printf("Discovering bridges via api.nuki.io...\n"); 29 | int httpResponseCode = _doAPIRequest(_NUKI_API_ENDPOINT_BRIDGEDISCOVERY, responseString, _NUKI_API_ENDPOINT_BRIDGEDISCOVERY_FINGERPRINT); 30 | JsonObject& root = jsonBuffer.parseObject(responseString); 31 | JsonArray& bridges = root["bridges"]; 32 | 33 | for (uint i = 0; i < bridges.size(); i++){ 34 | int bridgeID = bridges[i]["bridgeId"].as(); 35 | int bridgePort = bridges[i]["port"].as(); 36 | String bridgeIP = bridges[i]["ip"]; 37 | bridgeIPs.push_back(bridgeIP); 38 | bridgePorts.push_back(bridgePort); 39 | Serial.printf("Found bridge: %s:%u ( %u )\n", bridgeIP.c_str(), bridgePort, bridgeID); 40 | } 41 | 42 | if ((httpResponseCode == 200) && (root["errorCode"].as() == 0)) { 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | bool NukiClientESP::authenticateBridge(String &token){ 50 | String request = _fillAPITemplate(_NUKI_API_ENDPOINT_BRIDGEAUTH); 51 | String responseString; 52 | StaticJsonBuffer<1024> jsonBuffer; 53 | 54 | Serial.printf("Authenticating with bridge %s\n", _currentBridgeIP.c_str()); 55 | int httpResponseCode = _doAPIRequest(request,responseString); 56 | JsonObject& root = jsonBuffer.parseObject(responseString); 57 | 58 | if ((httpResponseCode == 200) && (root["success"].as() == true)) { 59 | token = root["token"].as(); 60 | Serial.printf("Acquired token: %s\n", token.c_str()); 61 | return true; 62 | } 63 | 64 | return false; 65 | } 66 | 67 | void NukiClientESP::useBridge(String bridgeIp, uint bridgePort){ 68 | _currentBridgeIP = bridgeIp; 69 | _currentBridgePort = bridgePort; 70 | } 71 | 72 | void NukiClientESP::useBridgeAuthToken(String bridgeAuthToken){ 73 | _currentBridgeAuthToken = bridgeAuthToken; 74 | } 75 | 76 | bool NukiClientESP::getBridgeInfo(String &bridgeInfoJSON){ 77 | String request = _fillAPITemplate(_NUKI_API_ENDPOINT_BRIDGEINFO); 78 | String responseString; 79 | StaticJsonBuffer<1024> jsonBuffer; 80 | 81 | Serial.printf("Getting info from bridge %s\n", _currentBridgeIP.c_str()); 82 | int httpResponseCode = _doAPIRequest(request,responseString); 83 | JsonObject& root = jsonBuffer.parseObject(responseString); 84 | 85 | if (httpResponseCode == 200) { 86 | root.prettyPrintTo(bridgeInfoJSON); 87 | Serial.printf("Info:\n%s\n", bridgeInfoJSON.c_str()); 88 | return true; 89 | } 90 | 91 | return false; 92 | } 93 | 94 | void NukiClientESP::useLock(uint lockID){ 95 | _currentLockID = lockID; 96 | } 97 | 98 | bool NukiClientESP::discoverLocks(std::vector &lockIDs){ 99 | String request = _fillAPITemplate(_NUKI_API_ENDPOINT_LOCKLIST); 100 | String responseString; 101 | StaticJsonBuffer<1024> jsonBuffer; 102 | int httpResponseCode = _doAPIRequest(request,responseString); 103 | JsonArray& root = jsonBuffer.parseArray(responseString); 104 | for (uint i = 0; i < root.size(); i++){ 105 | int lockID = root[i]["nukiId"].as(); 106 | String lockName = root[i]["name"]; 107 | lockIDs.push_back(lockID); 108 | Serial.printf("Found lock: %s ( %u )\n", lockName.c_str(), lockID); 109 | } 110 | 111 | if (httpResponseCode == 200) { 112 | return true; 113 | } 114 | 115 | return false; 116 | } 117 | 118 | bool NukiClientESP::triggerLockAction(NUKI_lock_actions lockAction){ 119 | String request = _fillAPITemplate(_NUKI_API_ENDPOINT_LOCKACTION); 120 | String responseString; 121 | StaticJsonBuffer<1024> jsonBuffer; 122 | 123 | request.replace("[ACTION]",String(lockAction)); 124 | Serial.printf("Triggering lock action: %u\n", lockAction); 125 | int httpResponseCode = _doAPIRequest(request,responseString); 126 | JsonObject& root = jsonBuffer.parseObject(responseString); 127 | 128 | if ((httpResponseCode == 200) && (root["success"].as() == true)) { 129 | return true; 130 | } 131 | 132 | return false; 133 | } 134 | 135 | bool NukiClientESP::lock(){ 136 | return triggerLockAction(NUKI_lock_actions::action_lock); 137 | } 138 | bool NukiClientESP::unlock(){ 139 | return triggerLockAction(NUKI_lock_actions::action_unlock); 140 | } 141 | bool NukiClientESP::unlatch(){ 142 | return triggerLockAction(NUKI_lock_actions::action_unlatch); 143 | } 144 | 145 | NukiClientESP::NUKI_lock_states NukiClientESP::getLockState(){ 146 | String request = _fillAPITemplate(_NUKI_API_ENDPOINT_LOCKSTATUS); 147 | String responseString; 148 | StaticJsonBuffer<1024> jsonBuffer; 149 | 150 | Serial.printf("Getting lock state\n"); 151 | int httpResponseCode = _doAPIRequest(request,responseString); 152 | JsonObject& root = jsonBuffer.parseObject(responseString); 153 | 154 | if ((httpResponseCode == 200) && (root["success"].as() == true)) { 155 | _currentLockState = (NUKI_lock_states)root["state"].as(); 156 | Serial.printf("Current state is: %s ( %u )\n", root["stateName"].as(), _currentLockState); 157 | return _currentLockState; 158 | } 159 | 160 | return NUKI_lock_states::state_undefined; 161 | } 162 | bool NukiClientESP::isLocked(){ 163 | return _currentLockState == NUKI_lock_states::state_locked; 164 | } 165 | 166 | String NukiClientESP::_fillAPITemplate(String apiTemplate){ 167 | apiTemplate.replace("[IP]",_currentBridgeIP); 168 | apiTemplate.replace("[PORT]",String(_currentBridgePort)); 169 | apiTemplate.replace("[TOKEN]",_currentBridgeAuthToken); 170 | apiTemplate.replace("[LOCK_ID]",String(_currentLockID)); 171 | apiTemplate.replace("[PORT]",String(_currentBridgePort)); 172 | return apiTemplate; 173 | } 174 | 175 | int NukiClientESP::_doAPIRequest(String requestURL, String& responseString, String SSLfingerprint){ 176 | int retries = 0; 177 | int httpCode = -255; 178 | //Serial.printf("Request URL: %s\n", requestURL.c_str()); 179 | if (SSLfingerprint == ""){ 180 | _http.begin(requestURL); 181 | } 182 | else{ 183 | _http.begin(requestURL,SSLfingerprint); 184 | } 185 | 186 | 187 | while(retries < _current_retries_max){ 188 | httpCode = _http.GET(); 189 | retries++; 190 | 191 | if (httpCode > 0){ 192 | if (httpCode == HTTP_CODE_OK) { 193 | responseString = _http.getString(); 194 | break; 195 | } 196 | else{ 197 | Serial.printf("[HTTP] GET... failed, error (%i): %s\n", httpCode, _http.errorToString(httpCode).c_str()); 198 | delay(_current_retries_timeout); 199 | } 200 | 201 | } 202 | else{ 203 | Serial.printf("[HTTP] GET... failed, error (%i): %s\n", httpCode, _http.errorToString(httpCode).c_str()); 204 | delay(_current_retries_timeout); 205 | } 206 | } 207 | 208 | _http.end(); 209 | //Serial.println(responseString.c_str()); 210 | //Serial.println(httpCode); 211 | return httpCode; 212 | } -------------------------------------------------------------------------------- /src/NukiClientESP.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class NukiClientESP { 8 | public: 9 | ///////////////////////////////////////////////////////////////////////////////////// 10 | // Enums for mapping responses and actions 11 | ///////////////////////////////////////////////////////////////////////////////////// 12 | enum NUKI_lock_states : byte { 13 | state_uncalibrated = 0, 14 | state_locked = 1, 15 | state_unlocking = 2, 16 | state_unlocked = 3, 17 | state_locking = 4, 18 | state_unlatched = 5, 19 | state_unlocked_lockngo = 6, 20 | state_unlatching = 7, 21 | state_motor_blocked = 254, 22 | state_undefined = 255 23 | }; 24 | 25 | enum NUKI_lock_actions : byte { 26 | action_unlock = 1, 27 | action_lock = 2, 28 | action_unlatch = 3, 29 | action_lockngo = 4, 30 | action_lockngo_with_unlatch = 5 31 | }; 32 | 33 | enum NUKI_http_responses : int { 34 | response_invalid_action = 400, 35 | response_invalid_token = 401, 36 | response_authentication_disabled = 403, 37 | response_samrtlock_unknown = 404, 38 | response_smartlock_offline = 503 39 | }; 40 | 41 | ///////////////////////////////////////////////////////////////////////////////////// 42 | // Functions for setting up the Library 43 | ///////////////////////////////////////////////////////////////////////////////////// 44 | NukiClientESP(); 45 | NukiClientESP(String bridgeIp, uint bridgePort); 46 | NukiClientESP(String bridgeIp, uint bridgePort, String bridgeAuthToken); 47 | NukiClientESP(String bridgeIp, uint bridgePort, String bridgeAuthToken, uint lockID); 48 | 49 | bool discoverBridges(std::vector &bridgeIPs, std::vector &bridgePorts); 50 | bool authenticateBridge(String &token); 51 | void useBridge(String bridgeIp, uint bridgePort); 52 | void useBridgeAuthToken(String authToken); 53 | 54 | bool discoverLocks(std::vector &lockIDs); 55 | void useLock(uint lockID); 56 | 57 | 58 | 59 | ///////////////////////////////////////////////////////////////////////////////////// 60 | // Functions for controlling the lock 61 | ///////////////////////////////////////////////////////////////////////////////////// 62 | bool triggerLockAction(NUKI_lock_actions lockAction); 63 | bool lock(); 64 | bool unlock(); 65 | bool unlatch(); 66 | 67 | ///////////////////////////////////////////////////////////////////////////////////// 68 | // Functions for getting the lock state 69 | ///////////////////////////////////////////////////////////////////////////////////// 70 | NUKI_lock_states getLockState(); 71 | bool isLocked(); 72 | bool getBridgeInfo(String &bridgeInfoJSON); 73 | 74 | protected: 75 | ///////////////////////////////////////////////////////////////////////////////////// 76 | // API endpoint strings 77 | ///////////////////////////////////////////////////////////////////////////////////// 78 | String _NUKI_API_ENDPOINT_BRIDGEAUTH = "http://[IP]:[PORT]/auth"; 79 | String _NUKI_API_ENDPOINT_BRIDGEINFO = "http://[IP]:[PORT]/info?token=[TOKEN]"; 80 | String _NUKI_API_ENDPOINT_LOCKLIST = "http://[IP]:[PORT]/list?token=[TOKEN]"; 81 | String _NUKI_API_ENDPOINT_LOCKSTATUS = "http://[IP]:[PORT]/lockState?token=[TOKEN]&nukiID=[LOCK_ID]"; 82 | String _NUKI_API_ENDPOINT_LOCKACTION = "http://[IP]:[PORT]/lockAction?token=[TOKEN]&nukiID=[LOCK_ID]&action=[ACTION]"; 83 | String _NUKI_API_ENDPOINT_BRIDGEDISCOVERY = "https://api.nuki.io/discover/bridges"; 84 | String _NUKI_API_ENDPOINT_BRIDGEDISCOVERY_FINGERPRINT = "e5a7c95ba444be76cc1e9120eb1be594486e7cd6"; 85 | 86 | ///////////////////////////////////////////////////////////////////////////////////// 87 | // variables 88 | ///////////////////////////////////////////////////////////////////////////////////// 89 | String _currentBridgeIP = ""; 90 | uint _currentBridgePort = 0; 91 | String _currentBridgeAuthToken = ""; 92 | uint _currentLockID = 0; 93 | NUKI_lock_states _currentLockState = NUKI_lock_states::state_undefined; 94 | //how often to retry if we cant connect to the bridge or the bridge tells the lock is offline 95 | int _current_retries_max = 3; 96 | int _current_retries_timeout = 250; //retry delay in ms 97 | 98 | HTTPClient _http; 99 | 100 | ///////////////////////////////////////////////////////////////////////////////////// 101 | // helpers 102 | ///////////////////////////////////////////////////////////////////////////////////// 103 | 104 | String _fillAPITemplate(String apiTemplate); 105 | int _doAPIRequest(String requestURL, String& responseString, String SSLfingerprint = ""); 106 | }; --------------------------------------------------------------------------------