AI added possibility to add two additional locks.
Some checks failed
NukiHub / Build esp32-gl-s10 (release) (push) Waiting to run
NukiHub / Build esp32-c3 (release) (push) Failing after 21m55s
NukiHub / Build esp32-c5 (release) (push) Failing after 14m56s
NukiHub / Build esp32-c61 (release) (push) Failing after 9m31s
NukiHub / Build esp32 (release) (push) Failing after 3h0m37s
NukiHub / Build esp32-c6 (release) (push) Failing after 14m45s
NukiHub / Build esp32-nopsram (release) (push) Has been cancelled
NukiHub / Build esp32-p4 (release) (push) Has been cancelled
NukiHub / Build esp32-p4c5 (release) (push) Has been cancelled
NukiHub / Build esp32-s3 (release) (push) Has been cancelled
NukiHub / Build esp32-s3-nopsram (release) (push) Has been cancelled
NukiHub / Build esp32-s3-oct (release) (push) Has been cancelled
NukiHub / Build esp32-solo1 (release) (push) Has been cancelled
NukiHub / Build esp32-h2 (release) (push) Has been cancelled
Some checks failed
NukiHub / Build esp32-gl-s10 (release) (push) Waiting to run
NukiHub / Build esp32-c3 (release) (push) Failing after 21m55s
NukiHub / Build esp32-c5 (release) (push) Failing after 14m56s
NukiHub / Build esp32-c61 (release) (push) Failing after 9m31s
NukiHub / Build esp32 (release) (push) Failing after 3h0m37s
NukiHub / Build esp32-c6 (release) (push) Failing after 14m45s
NukiHub / Build esp32-nopsram (release) (push) Has been cancelled
NukiHub / Build esp32-p4 (release) (push) Has been cancelled
NukiHub / Build esp32-p4c5 (release) (push) Has been cancelled
NukiHub / Build esp32-s3 (release) (push) Has been cancelled
NukiHub / Build esp32-s3-nopsram (release) (push) Has been cancelled
NukiHub / Build esp32-s3-oct (release) (push) Has been cancelled
NukiHub / Build esp32-solo1 (release) (push) Has been cancelled
NukiHub / Build esp32-h2 (release) (push) Has been cancelled
* only ESP32-C3 * only Smart Lock Go
This commit is contained in:
31
README.md
31
README.md
@@ -185,6 +185,28 @@ Before enabling pairing mode using the button on the Nuki Lock Ultra / Nuki Lock
|
||||
|
||||
When pairing is successful, the web interface should show "Paired: Yes".<br>
|
||||
|
||||
## Pairing additional locks (Slot 2 and Slot 3)
|
||||
|
||||
Nuki Hub supports up to 3 locks on a single ESP/device IP.
|
||||
|
||||
To pair additional locks:
|
||||
- Go to "Nuki Configuration" and enable "Nuki Lock slot 2 enabled" and/or "Nuki Lock slot 3 enabled", then Save.
|
||||
- Go to "MQTT Configuration" and set "Lock Slot 2 MQTT Name" / "Lock Slot 3 MQTT Name", then Save.
|
||||
- Put the corresponding lock into Bluetooth pairing mode using the lock button.
|
||||
- Pairing for slot 2/3 is automatic while the slot is enabled and not yet paired.
|
||||
|
||||
How this is shown:
|
||||
- On the info page, check "NUKI LOCK SLOT 2" and "NUKI LOCK SLOT 3" sections.
|
||||
- MQTT topics are published per slot name:
|
||||
- `<mqtt_path>/<slot_1_mqtt_name>/...`
|
||||
- `<mqtt_path>/<slot_2_mqtt_name>/...`
|
||||
- `<mqtt_path>/<slot_3_mqtt_name>/...`
|
||||
|
||||
Unpairing slot 2/3 in web interface:
|
||||
- Open "Credentials".
|
||||
- Use "Unpair Nuki Lock Slot 2" or "Unpair Nuki Lock Slot 3".
|
||||
- Enter the shown 4 digit confirmation code.
|
||||
|
||||
## Hybrid mode
|
||||
|
||||
Hybrid mode allows you to use the official Nuki MQTT implementation on a Nuki Lock 3.0 Pro, Nuki Lock 4.0, Nuki Lock 4.0 Pro, Nuki Lock 5.0 Pro, Nuki Lock Go or Nuki Lock Ultra in conjunction with Nuki Hub.<br>
|
||||
@@ -265,6 +287,9 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
- MQTT User: If using authentication on the MQTT broker set to a username with read/write rights on the MQTT broker, set to # to clear
|
||||
- MQTT Password : If using authentication on the MQTT broker set to the password belonging to a username with read/write rights on the MQTT broker, set to # to clear
|
||||
- MQTT Nuki Hub Path: Set to the preferred MQTT root topic for Nuki Hub, defaults to "nukihub". Make sure this topic is unique when using multiple ESP32 Nuki Hub devices
|
||||
- Lock Slot 1 MQTT Name: Set the MQTT topic name for lock slot 1 (default: `lock`)
|
||||
- Lock Slot 2 MQTT Name: Set the MQTT topic name for lock slot 2 (default: `lock2`)
|
||||
- Lock Slot 3 MQTT Name: Set the MQTT topic name for lock slot 3 (default: `lock3`)
|
||||
- Enable Home Assistant auto discovery: Enable Home Assistant MQTT auto discovery. Will automatically create entities in Home Assistant for Nuki Hub and connected Nuki Lock and/or Opener when enabled.
|
||||
|
||||
#### Advanced MQTT Configuration
|
||||
@@ -289,6 +314,8 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
#### Basic Nuki Configuration
|
||||
|
||||
- Nuki Smartlock enabled: Enable if you want Nuki Hub to connect to a Nuki Lock (All versions)
|
||||
- Nuki Lock slot 2 enabled: Enable if you want Nuki Hub to connect to a second Nuki Lock
|
||||
- Nuki Lock slot 3 enabled: Enable if you want Nuki Hub to connect to a third Nuki Lock
|
||||
- Nuki Smartlock Ultra/Go/5th gen enabled: Enable if you want Nuki Hub to connect to a Nuki Lock Ultra/Go/5th gen Pro
|
||||
- Nuki Opener enabled: Enable if you want Nuki Hub to connect to a Nuki Opener
|
||||
|
||||
@@ -366,9 +393,9 @@ Note: All of the following requires the Nuki security code / PIN to be set, see
|
||||
- PIN Code: Fill with the Nuki Security Code of the Nuki Lock and/or Nuki Opener. Required for functions that require the security code to be sent to the lock/opener such as setting lock permissions/adding keypad codes, viewing the activity log or changing the Nuki device configuration. Set to "#" to remove the security code from the Nuki Hub configuration.
|
||||
- PIN Code Ultra/5th gen: Fill with the 6-digit Nuki Security Code of the Nuki Lock Ultra/Go/5th gen Pro. Required for pairing (and many other functions)
|
||||
|
||||
#### Unpair Nuki Lock / Unpair Nuki Opener
|
||||
#### Unpair Nuki Lock / Unpair Nuki Lock Slot 2 / Unpair Nuki Lock Slot 3 / Unpair Nuki Opener
|
||||
|
||||
- Type [4 DIGIT CODE] to confirm unpair: Set to the shown randomly generated code to unpair the Nuki Lock or Opener from the Nuki Hub.
|
||||
- Type [4 DIGIT CODE] to confirm unpair: Set to the shown randomly generated code to unpair the selected Nuki device from the Nuki Hub.
|
||||
|
||||
#### Factory reset Nuki Hub
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#define NUKI_HUB_VERSION "9.15"
|
||||
#define NUKI_HUB_VERSION_INT (uint32_t)915
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
#define NUKI_HUB_DATE "2026-01-09"
|
||||
#define NUKI_HUB_DATE "2026-01-09"
|
||||
#define NUKI_HUB_DATE "2026-03-20"
|
||||
#define NUKI_HUB_DATE "2026-03-20"
|
||||
|
||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
||||
|
||||
@@ -19,7 +19,7 @@ HomeAssistantDiscovery::HomeAssistantDiscovery(NetworkDevice* device, Preference
|
||||
_hostname = _preferences->getString(preference_hostname, "");
|
||||
}
|
||||
|
||||
void HomeAssistantDiscovery::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad)
|
||||
void HomeAssistantDiscovery::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad, const char* topicOverride)
|
||||
{
|
||||
uint64_t savedDevId = _preferences->getULong64(preference_nukihub_id, 0);
|
||||
uint64_t curDevId;
|
||||
@@ -96,12 +96,11 @@ void HomeAssistantDiscovery::setupHASS(int type, uint32_t nukiId, char* nukiName
|
||||
}
|
||||
else if(type == 1)
|
||||
{
|
||||
if(_preferences->getUInt(preference_nuki_id_lock, 0) != nukiId)
|
||||
if(topicOverride == nullptr && _preferences->getUInt(preference_nuki_id_lock, 0) != nukiId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String lockTopic = _baseTopic;
|
||||
lockTopic.concat("/lock");
|
||||
String lockTopic = (topicOverride != nullptr) ? String(topicOverride) : _baseTopic + "/lock";
|
||||
publishHASSConfig((char*)"SmartLock", lockTopic.c_str(), nukiName, uidString, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad, publishAuthData, (char*)"lock", (char*)"unlock", (char*)"unlatch");
|
||||
Log->println("HomeAssistant setup for lock completed.");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ class HomeAssistantDiscovery
|
||||
{
|
||||
public:
|
||||
explicit HomeAssistantDiscovery(NetworkDevice* device, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
|
||||
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad, const char* topicOverride = nullptr);
|
||||
void disableHASS();
|
||||
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||
void publishHassTopic(const String& mqttDeviceType,
|
||||
@@ -67,4 +67,4 @@ private:
|
||||
|
||||
char* _buffer;
|
||||
const size_t _bufferSize;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,34 @@
|
||||
#include "PreferencesKeys.h"
|
||||
#include <DuoAuthLib.h>
|
||||
#include <TOTP-RC6236-generator.hpp>
|
||||
#include <ctype.h>
|
||||
|
||||
static String normalizeMqttLockName(String name)
|
||||
{
|
||||
name.trim();
|
||||
name.toLowerCase();
|
||||
return name;
|
||||
}
|
||||
|
||||
static bool isValidMqttLockName(const String& name)
|
||||
{
|
||||
if(name.length() < 3 || name.length() > 32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < name.length(); i++)
|
||||
{
|
||||
const char c = name.charAt(i);
|
||||
if((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ImportExport::ImportExport(Preferences *preferences)
|
||||
: _preferences(preferences)
|
||||
@@ -657,6 +685,22 @@ void ImportExport::exportNukiHubJson(JsonDocument &json, bool redacted, bool pai
|
||||
json[key] = text;
|
||||
memset(text, 0, sizeof(text));
|
||||
}
|
||||
|
||||
JsonArray locks = json["locks"].to<JsonArray>();
|
||||
JsonObject lock1 = locks.add<JsonObject>();
|
||||
lock1["slot"] = 1;
|
||||
lock1["enabled"] = _preferences->getBool(preference_lock_enabled, true) ? "1" : "0";
|
||||
lock1["mqtt_name"] = _preferences->getString(preference_mqtt_lock_name_1, "lock");
|
||||
|
||||
JsonObject lock2 = locks.add<JsonObject>();
|
||||
lock2["slot"] = 2;
|
||||
lock2["enabled"] = _preferences->getBool(preference_lock_enabled_2, false) ? "1" : "0";
|
||||
lock2["mqtt_name"] = _preferences->getString(preference_mqtt_lock_name_2, "lock2");
|
||||
|
||||
JsonObject lock3 = locks.add<JsonObject>();
|
||||
lock3["slot"] = 3;
|
||||
lock3["enabled"] = _preferences->getBool(preference_lock_enabled_3, false) ? "1" : "0";
|
||||
lock3["mqtt_name"] = _preferences->getString(preference_mqtt_lock_name_3, "lock3");
|
||||
}
|
||||
|
||||
JsonDocument ImportExport::importJson(JsonDocument &doc)
|
||||
@@ -677,9 +721,97 @@ JsonDocument ImportExport::importJson(JsonDocument &doc)
|
||||
const std::vector<char*> intPrefs = debugPreferences.getPreferencesIntKeys();
|
||||
const std::vector<char*> uintPrefs = debugPreferences.getPreferencesUIntKeys();
|
||||
const std::vector<char*> uint64Prefs = debugPreferences.getPreferencesUInt64Keys();
|
||||
bool hasLocksArray = false;
|
||||
String importedLockNames[3] = {
|
||||
normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_1, "lock")),
|
||||
normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_2, "lock2")),
|
||||
normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_3, "lock3"))
|
||||
};
|
||||
bool importedLockEnabled[3] = {
|
||||
_preferences->getBool(preference_lock_enabled, true),
|
||||
_preferences->getBool(preference_lock_enabled_2, false),
|
||||
_preferences->getBool(preference_lock_enabled_3, false)
|
||||
};
|
||||
|
||||
if(!doc["locks"].isNull() && doc["locks"].is<JsonArray>())
|
||||
{
|
||||
hasLocksArray = true;
|
||||
JsonArray locks = doc["locks"].as<JsonArray>();
|
||||
if(locks.size() == 0 || locks.size() > 3)
|
||||
{
|
||||
json["_import_error"] = "Invalid locks array size (must be 1..3).";
|
||||
return json;
|
||||
}
|
||||
|
||||
for(JsonVariant v : locks)
|
||||
{
|
||||
if(!v.is<JsonObject>())
|
||||
{
|
||||
json["_import_error"] = "Invalid locks entry (must be object).";
|
||||
return json;
|
||||
}
|
||||
JsonObject o = v.as<JsonObject>();
|
||||
int slot = 0;
|
||||
if(!o["slot"].isNull())
|
||||
{
|
||||
slot = o["slot"].as<int>();
|
||||
}
|
||||
if(slot < 1 || slot > 3)
|
||||
{
|
||||
json["_import_error"] = "Invalid lock slot in import (must be 1..3).";
|
||||
return json;
|
||||
}
|
||||
|
||||
if(o["mqtt_name"].isNull())
|
||||
{
|
||||
json["_import_error"] = "Missing locks[].mqtt_name.";
|
||||
return json;
|
||||
}
|
||||
|
||||
String lockName = normalizeMqttLockName(o["mqtt_name"].as<String>());
|
||||
if(!isValidMqttLockName(lockName))
|
||||
{
|
||||
json["_import_error"] = "Invalid locks[].mqtt_name (allowed: a-z,0-9,_,-; length 3..32).";
|
||||
return json;
|
||||
}
|
||||
importedLockNames[slot - 1] = lockName;
|
||||
|
||||
if(!o["enabled"].isNull())
|
||||
{
|
||||
if(o["enabled"].is<bool>())
|
||||
{
|
||||
importedLockEnabled[slot - 1] = o["enabled"].as<bool>();
|
||||
}
|
||||
else
|
||||
{
|
||||
const String enabledVal = o["enabled"].as<String>();
|
||||
importedLockEnabled[slot - 1] = (enabledVal == "1" || enabledVal == "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(importedLockNames[0] == importedLockNames[1] ||
|
||||
importedLockNames[0] == importedLockNames[2] ||
|
||||
importedLockNames[1] == importedLockNames[2])
|
||||
{
|
||||
json["_import_error"] = "Duplicate locks[].mqtt_name is not allowed.";
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto& key : keysPrefs)
|
||||
{
|
||||
if(hasLocksArray &&
|
||||
(strcmp(key, preference_mqtt_lock_name_1) == 0 ||
|
||||
strcmp(key, preference_mqtt_lock_name_2) == 0 ||
|
||||
strcmp(key, preference_mqtt_lock_name_3) == 0 ||
|
||||
strcmp(key, preference_lock_enabled) == 0 ||
|
||||
strcmp(key, preference_lock_enabled_2) == 0 ||
|
||||
strcmp(key, preference_lock_enabled_3) == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(doc[key].isNull())
|
||||
{
|
||||
continue;
|
||||
@@ -760,6 +892,21 @@ JsonDocument ImportExport::importJson(JsonDocument &doc)
|
||||
}
|
||||
}
|
||||
|
||||
if(hasLocksArray)
|
||||
{
|
||||
_preferences->putString(preference_mqtt_lock_name_1, importedLockNames[0]);
|
||||
_preferences->putString(preference_mqtt_lock_name_2, importedLockNames[1]);
|
||||
_preferences->putString(preference_mqtt_lock_name_3, importedLockNames[2]);
|
||||
_preferences->putBool(preference_lock_enabled, importedLockEnabled[0]);
|
||||
_preferences->putBool(preference_lock_enabled_2, importedLockEnabled[1]);
|
||||
_preferences->putBool(preference_lock_enabled_3, importedLockEnabled[2]);
|
||||
if(importedLockEnabled[1] || importedLockEnabled[2])
|
||||
{
|
||||
_preferences->putBool(preference_opener_enabled, false);
|
||||
}
|
||||
json["locks"] = "changed";
|
||||
}
|
||||
|
||||
for(const auto& key : bytePrefs)
|
||||
{
|
||||
if(!doc[key].isNull() && doc[key].is<JsonVariant>())
|
||||
@@ -1144,4 +1291,4 @@ JsonDocument ImportExport::importJson(JsonDocument &doc)
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,17 +821,38 @@ bool NukiNetwork::reconnect(bool force)
|
||||
|
||||
if(_preferences->getBool(preference_reset_mqtt_topics, false))
|
||||
{
|
||||
char mqttLockPath[181] = {0};
|
||||
char mqttLockPath1[181] = {0};
|
||||
char mqttLockPath2[181] = {0};
|
||||
char mqttLockPath3[181] = {0};
|
||||
char mqttOpenerPath[181] = {0};
|
||||
char mqttOldOpenerPath[181] = {0};
|
||||
char mqttOldOpenerPath2[181] = {0};
|
||||
String mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
mqttPath.concat("/lock");
|
||||
mqttPath.concat("/");
|
||||
mqttPath.concat(_preferences->getString(preference_mqtt_lock_name_1, "lock"));
|
||||
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
mqttLockPath[i] = mqttPath.charAt(i);
|
||||
mqttLockPath1[i] = mqttPath.charAt(i);
|
||||
}
|
||||
|
||||
mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
mqttPath.concat("/");
|
||||
mqttPath.concat(_preferences->getString(preference_mqtt_lock_name_2, "lock2"));
|
||||
len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
mqttLockPath2[i] = mqttPath.charAt(i);
|
||||
}
|
||||
|
||||
mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
mqttPath.concat("/");
|
||||
mqttPath.concat(_preferences->getString(preference_mqtt_lock_name_3, "lock3"));
|
||||
len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
{
|
||||
mqttLockPath3[i] = mqttPath.charAt(i);
|
||||
}
|
||||
|
||||
mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
@@ -867,7 +888,9 @@ bool NukiNetwork::reconnect(bool force)
|
||||
for(const auto& topic : mqttTopicsKeys)
|
||||
{
|
||||
removeTopic(_maintenancePathPrefix, topic);
|
||||
removeTopic(mqttLockPath, topic);
|
||||
removeTopic(mqttLockPath1, topic);
|
||||
removeTopic(mqttLockPath2, topic);
|
||||
removeTopic(mqttLockPath3, topic);
|
||||
removeTopic(mqttOpenerPath, topic);
|
||||
if (len > 5)
|
||||
{
|
||||
@@ -1536,9 +1559,9 @@ void NukiNetwork::removeTopic(const String& mqttPath, const String& mqttTopic)
|
||||
#endif
|
||||
}
|
||||
|
||||
void NukiNetwork::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad)
|
||||
void NukiNetwork::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad, const char* topicOverride)
|
||||
{
|
||||
_hadiscovery->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad);
|
||||
_hadiscovery->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad, topicOverride);
|
||||
}
|
||||
|
||||
void NukiNetwork::disableHASS()
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
|
||||
void timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str);
|
||||
|
||||
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
|
||||
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad, const char* topicOverride = nullptr);
|
||||
void disableHASS();
|
||||
void publishHassTopic(const String& mqttDeviceType,
|
||||
const String& mqttDeviceName,
|
||||
@@ -183,4 +183,4 @@ private:
|
||||
|
||||
int8_t _lastRssi = 127;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,12 +14,38 @@ extern bool forceEnableWebServer;
|
||||
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_bundle_start");
|
||||
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end");
|
||||
|
||||
NukiNetworkLock::NukiNetworkLock(NukiNetwork* network, NukiOfficial* nukiOfficial, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
static String normalizedLockMqttName(Preferences* preferences, const char* prefKey)
|
||||
{
|
||||
String in = preferences->getString(prefKey, "lock");
|
||||
in.trim();
|
||||
in.toLowerCase();
|
||||
|
||||
String out;
|
||||
out.reserve(in.length());
|
||||
for(size_t i = 0; i < in.length(); i++)
|
||||
{
|
||||
const char c = in.charAt(i);
|
||||
if((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-')
|
||||
{
|
||||
out.concat(c);
|
||||
}
|
||||
}
|
||||
|
||||
if(out.length() < 3 || out.length() > 32)
|
||||
{
|
||||
return String("lock");
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
NukiNetworkLock::NukiNetworkLock(NukiNetwork* network, NukiOfficial* nukiOfficial, Preferences* preferences, char* buffer, size_t bufferSize, uint8_t lockSlot)
|
||||
: _network(network),
|
||||
_nukiOfficial(nukiOfficial),
|
||||
_preferences(preferences),
|
||||
_buffer(buffer),
|
||||
_bufferSize(bufferSize)
|
||||
_bufferSize(bufferSize),
|
||||
_lockSlot(lockSlot)
|
||||
{
|
||||
_nukiPublisher = new NukiPublisher(network, _mqttPath);
|
||||
_nukiOfficial->setPublisher(_nukiPublisher);
|
||||
@@ -42,7 +68,8 @@ void NukiNetworkLock::initialize()
|
||||
}
|
||||
|
||||
String mqttPath = _preferences->getString(preference_mqtt_lock_path, "");
|
||||
mqttPath.concat("/lock");
|
||||
mqttPath.concat("/");
|
||||
mqttPath.concat(normalizedLockMqttName(_preferences, mqttNamePreferenceKey()));
|
||||
|
||||
size_t len = mqttPath.length();
|
||||
for(int i=0; i < len; i++)
|
||||
@@ -151,7 +178,7 @@ void NukiNetworkLock::initialize()
|
||||
|
||||
if(_nukiOfficial->getOffEnabled())
|
||||
{
|
||||
_nukiOfficial->setUid(_preferences->getUInt(preference_nuki_id_lock, 0));
|
||||
_nukiOfficial->setUid(_preferences->getUInt(nukiIdPreferenceKey(), 0));
|
||||
|
||||
for(const auto& offTopic : _nukiOfficial->getOffTopics())
|
||||
{
|
||||
@@ -252,7 +279,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
|
||||
Log->print("Lock action received: ");
|
||||
Log->println(data);
|
||||
LockActionResult lockActionResult = LockActionResult::Failed;
|
||||
if(_lockActionReceivedCallback != NULL)
|
||||
if(_lockActionReceivedCallback)
|
||||
{
|
||||
lockActionResult = _lockActionReceivedCallback(data);
|
||||
}
|
||||
@@ -348,7 +375,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
|
||||
return;
|
||||
}
|
||||
|
||||
if(_configUpdateReceivedCallback != NULL)
|
||||
if(_configUpdateReceivedCallback)
|
||||
{
|
||||
_configUpdateReceivedCallback(data);
|
||||
}
|
||||
@@ -363,7 +390,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
|
||||
return;
|
||||
}
|
||||
|
||||
if(_keypadJsonCommandReceivedReceivedCallback != NULL)
|
||||
if(_keypadJsonCommandReceivedReceivedCallback)
|
||||
{
|
||||
_keypadJsonCommandReceivedReceivedCallback(data);
|
||||
}
|
||||
@@ -378,7 +405,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
|
||||
return;
|
||||
}
|
||||
|
||||
if(_timeControlCommandReceivedReceivedCallback != NULL)
|
||||
if(_timeControlCommandReceivedReceivedCallback)
|
||||
{
|
||||
_timeControlCommandReceivedReceivedCallback(data);
|
||||
}
|
||||
@@ -393,7 +420,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
|
||||
return;
|
||||
}
|
||||
|
||||
if(_authCommandReceivedReceivedCallback != NULL)
|
||||
if(_authCommandReceivedReceivedCallback)
|
||||
{
|
||||
_authCommandReceivedReceivedCallback(data);
|
||||
}
|
||||
@@ -1011,9 +1038,8 @@ void NukiNetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entr
|
||||
bool topicPerEntry = _preferences->getBool(preference_keypad_topic_per_entry, false);
|
||||
uint index = 0;
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
itoa(_preferences->getUInt(nukiIdPreferenceKey(), 0), uidString, 16);
|
||||
String baseTopic = _mqttPath;
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : entries)
|
||||
@@ -1216,9 +1242,8 @@ void NukiNetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEn
|
||||
uint index = 0;
|
||||
char str[50];
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
itoa(_preferences->getUInt(nukiIdPreferenceKey(), 0), uidString, 16);
|
||||
String baseTopic = _mqttPath;
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : timeControlEntries)
|
||||
@@ -1349,9 +1374,8 @@ void NukiNetworkLock::publishAuth(const std::list<NukiLock::AuthorizationEntry>&
|
||||
uint index = 0;
|
||||
char str[50];
|
||||
char uidString[20];
|
||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
||||
baseTopic.concat("/lock");
|
||||
itoa(_preferences->getUInt(nukiIdPreferenceKey(), 0), uidString, 16);
|
||||
String baseTopic = _mqttPath;
|
||||
JsonDocument json;
|
||||
|
||||
for(const auto& entry : authEntries)
|
||||
@@ -1529,22 +1553,22 @@ void NukiNetworkLock::publishStatusUpdated(const bool statusUpdated)
|
||||
_nukiPublisher->publishBool(mqtt_topic_lock_status_updated, statusUpdated, true);
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setLockActionReceivedCallback(std::function<LockActionResult(const char* value)> lockActionReceivedCallback)
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setOfficialUpdateReceivedCallback(void (*officialUpdateReceivedCallback)(const char *, const char *))
|
||||
void NukiNetworkLock::setOfficialUpdateReceivedCallback(std::function<void(const char* path, const char* value)> officialUpdateReceivedCallback)
|
||||
{
|
||||
_officialUpdateReceivedCallback = officialUpdateReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setConfigUpdateReceivedCallback(std::function<void(const char* value)> configUpdateReceivedCallback)
|
||||
{
|
||||
_configUpdateReceivedCallback = configUpdateReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled))
|
||||
void NukiNetworkLock::setKeypadCommandReceivedCallback(std::function<void(const char* command, const uint& id, const String& name, const String& code, const int& enabled)> keypadCommandReceivedReceivedCallback)
|
||||
{
|
||||
if(_disableNonJSON)
|
||||
{
|
||||
@@ -1553,21 +1577,47 @@ void NukiNetworkLock::setKeypadCommandReceivedCallback(void (*keypadCommandRecei
|
||||
_keypadCommandReceivedReceivedCallback = keypadCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setKeypadJsonCommandReceivedCallback(std::function<void(const char* value)> keypadJsonCommandReceivedReceivedCallback)
|
||||
{
|
||||
_keypadJsonCommandReceivedReceivedCallback = keypadJsonCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setTimeControlCommandReceivedCallback(std::function<void(const char* value)> timeControlCommandReceivedReceivedCallback)
|
||||
{
|
||||
_timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
void NukiNetworkLock::setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char *))
|
||||
void NukiNetworkLock::setAuthCommandReceivedCallback(std::function<void(const char* value)> authCommandReceivedReceivedCallback)
|
||||
{
|
||||
_authCommandReceivedReceivedCallback = authCommandReceivedReceivedCallback;
|
||||
}
|
||||
|
||||
const char* NukiNetworkLock::nukiIdPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_nuki_id_lock_2;
|
||||
case 3:
|
||||
return preference_nuki_id_lock_3;
|
||||
default:
|
||||
return preference_nuki_id_lock;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiNetworkLock::mqttNamePreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_mqtt_lock_name_2;
|
||||
case 3:
|
||||
return preference_mqtt_lock_name_3;
|
||||
default:
|
||||
return preference_mqtt_lock_name_1;
|
||||
}
|
||||
}
|
||||
|
||||
void NukiNetworkLock::buildMqttPath(const char* path, char* outPath)
|
||||
{
|
||||
int offset = 0;
|
||||
@@ -1627,7 +1677,7 @@ const uint8_t NukiNetworkLock::queryCommands()
|
||||
|
||||
void NukiNetworkLock::setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad)
|
||||
{
|
||||
_network->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad);
|
||||
_network->setupHASS(type, nukiId, nukiName, firmwareVersion, hardwareVersion, hasDoorSensor, hasKeypad, _mqttPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -1647,4 +1697,4 @@ const char* NukiNetworkLock::getAuthName()
|
||||
return _authEntries[getAuthId()].c_str();
|
||||
}
|
||||
return _authName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
#include "NukiOfficial.h"
|
||||
#include "NukiPublisher.h"
|
||||
#include "EspMillis.h"
|
||||
#include <functional>
|
||||
|
||||
class NukiNetworkLock : public MqttReceiver
|
||||
{
|
||||
public:
|
||||
explicit NukiNetworkLock(NukiNetwork* network, NukiOfficial* nukiOfficial, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
explicit NukiNetworkLock(NukiNetwork* network, NukiOfficial* nukiOfficial, Preferences* preferences, char* buffer, size_t bufferSize, uint8_t lockSlot = 1);
|
||||
virtual ~NukiNetworkLock();
|
||||
|
||||
void initialize();
|
||||
@@ -48,13 +49,13 @@ public:
|
||||
void publishAuthCommandResult(const char* result);
|
||||
void publishOffAction(const int value);
|
||||
|
||||
void setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char* value));
|
||||
void setOfficialUpdateReceivedCallback(void (*officialUpdateReceivedCallback)(const char* path, const char* value));
|
||||
void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* value));
|
||||
void setKeypadCommandReceivedCallback(void (*keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled));
|
||||
void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value));
|
||||
void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value));
|
||||
void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value));
|
||||
void setLockActionReceivedCallback(std::function<LockActionResult(const char* value)> lockActionReceivedCallback);
|
||||
void setOfficialUpdateReceivedCallback(std::function<void(const char* path, const char* value)> officialUpdateReceivedCallback);
|
||||
void setConfigUpdateReceivedCallback(std::function<void(const char* value)> configUpdateReceivedCallback);
|
||||
void setKeypadCommandReceivedCallback(std::function<void(const char* command, const uint& id, const String& name, const String& code, const int& enabled)> keypadCommandReceivedReceivedCallback);
|
||||
void setKeypadJsonCommandReceivedCallback(std::function<void(const char* value)> keypadJsonCommandReceivedReceivedCallback);
|
||||
void setTimeControlCommandReceivedCallback(std::function<void(const char* value)> timeControlCommandReceivedReceivedCallback);
|
||||
void setAuthCommandReceivedCallback(std::function<void(const char* value)> authCommandReceivedReceivedCallback);
|
||||
void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override;
|
||||
void setupHASS(int type, uint32_t nukiId, char* nukiName, const char* firmwareVersion, const char* hardwareVersion, bool hasDoorSensor, bool hasKeypad);
|
||||
|
||||
@@ -65,11 +66,11 @@ public:
|
||||
|
||||
private:
|
||||
const bool comparePrefixedPath(const char* fullPath, const char* subPath);
|
||||
const char* nukiIdPreferenceKey() const;
|
||||
const char* mqttNamePreferenceKey() const;
|
||||
|
||||
void publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry);
|
||||
|
||||
void (*_officialUpdateReceivedCallback)(const char* path, const char* value) = nullptr;
|
||||
|
||||
String concat(String a, String b);
|
||||
|
||||
void buildMqttPath(const char* path, char* outPath);
|
||||
@@ -102,14 +103,16 @@ private:
|
||||
|
||||
char _nukiName[33];
|
||||
char _authName[33];
|
||||
uint8_t _lockSlot = 1;
|
||||
|
||||
char* _buffer;
|
||||
size_t _bufferSize;
|
||||
|
||||
LockActionResult (*_lockActionReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_configUpdateReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_keypadCommandReceivedReceivedCallback)(const char* command, const uint& id, const String& name, const String& code, const int& enabled) = nullptr;
|
||||
void (*_keypadJsonCommandReceivedReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_timeControlCommandReceivedReceivedCallback)(const char* value) = nullptr;
|
||||
void (*_authCommandReceivedReceivedCallback)(const char* value) = nullptr;
|
||||
};
|
||||
std::function<LockActionResult(const char* value)> _lockActionReceivedCallback = nullptr;
|
||||
std::function<void(const char* path, const char* value)> _officialUpdateReceivedCallback = nullptr;
|
||||
std::function<void(const char* value)> _configUpdateReceivedCallback = nullptr;
|
||||
std::function<void(const char* command, const uint& id, const String& name, const String& code, const int& enabled)> _keypadCommandReceivedReceivedCallback = nullptr;
|
||||
std::function<void(const char* value)> _keypadJsonCommandReceivedReceivedCallback = nullptr;
|
||||
std::function<void(const char* value)> _timeControlCommandReceivedReceivedCallback = nullptr;
|
||||
std::function<void(const char* value)> _authCommandReceivedReceivedCallback = nullptr;
|
||||
};
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "util/NukiHelper.h"
|
||||
#include "util/NukiRetryHandler.h"
|
||||
|
||||
NukiWrapper* nukiInst = nullptr;
|
||||
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize)
|
||||
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize, uint8_t lockSlot)
|
||||
: _deviceName(deviceName),
|
||||
_deviceId(deviceId),
|
||||
_bleScanner(scanner),
|
||||
@@ -23,6 +21,7 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
|
||||
_nukiOfficial(nukiOfficial),
|
||||
_gpio(gpio),
|
||||
_preferences(preferences),
|
||||
_lockSlot(lockSlot),
|
||||
_buffer(buffer),
|
||||
_bufferSize(bufferSize)
|
||||
{
|
||||
@@ -30,23 +29,48 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
|
||||
Log->print("Device id lock: ");
|
||||
Log->println(_deviceId->get());
|
||||
|
||||
nukiInst = this;
|
||||
|
||||
memset(&_lastKeyTurnerState, sizeof(NukiLock::KeyTurnerState), 0);
|
||||
memset(&_lastBatteryReport, sizeof(NukiLock::BatteryReport), 0);
|
||||
memset(&_batteryReport, sizeof(NukiLock::BatteryReport), 0);
|
||||
memset(&_keyTurnerState, sizeof(NukiLock::KeyTurnerState), 0);
|
||||
_keyTurnerState.lockState = NukiLock::LockState::Undefined;
|
||||
|
||||
network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback);
|
||||
network->setOfficialUpdateReceivedCallback(nukiInst->onOfficialUpdateReceivedCallback);
|
||||
network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback);
|
||||
network->setKeypadCommandReceivedCallback(nukiInst->onKeypadCommandReceivedCallback);
|
||||
network->setKeypadJsonCommandReceivedCallback(nukiInst->onKeypadJsonCommandReceivedCallback);
|
||||
network->setTimeControlCommandReceivedCallback(nukiInst->onTimeControlCommandReceivedCallback);
|
||||
network->setAuthCommandReceivedCallback(nukiInst->onAuthCommandReceivedCallback);
|
||||
network->setLockActionReceivedCallback([this](const char* value)
|
||||
{
|
||||
return onLockActionReceived(value);
|
||||
});
|
||||
network->setOfficialUpdateReceivedCallback([this](const char* topic, const char* value)
|
||||
{
|
||||
onOfficialUpdateReceived(topic, value);
|
||||
});
|
||||
network->setConfigUpdateReceivedCallback([this](const char* value)
|
||||
{
|
||||
onConfigUpdateReceived(value);
|
||||
});
|
||||
network->setKeypadCommandReceivedCallback([this](const char* command, const uint& id, const String& name, const String& code, const int& enabled)
|
||||
{
|
||||
onKeypadCommandReceived(command, id, name, code, enabled);
|
||||
});
|
||||
network->setKeypadJsonCommandReceivedCallback([this](const char* value)
|
||||
{
|
||||
onKeypadJsonCommandReceived(value);
|
||||
});
|
||||
network->setTimeControlCommandReceivedCallback([this](const char* value)
|
||||
{
|
||||
onTimeControlCommandReceived(value);
|
||||
});
|
||||
network->setAuthCommandReceivedCallback([this](const char* value)
|
||||
{
|
||||
onAuthCommandReceived(value);
|
||||
});
|
||||
|
||||
_gpio->addCallback(NukiWrapper::gpioActionCallback);
|
||||
if(_lockSlot == 1)
|
||||
{
|
||||
_gpio->addCallback([this](const GpioAction& action, const int& pin)
|
||||
{
|
||||
onGpioActionReceived(action, pin);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +180,9 @@ void NukiWrapper::readSettings()
|
||||
_intervalKeypad = _preferences->getInt(preference_query_interval_keypad);
|
||||
_keypadEnabled = _preferences->getBool(preference_keypad_info_enabled);
|
||||
_publishAuthData = _preferences->getBool(preference_publish_authdata);
|
||||
_maxKeypadCodeCount = _preferences->getUInt(preference_lock_max_keypad_code_count);
|
||||
_maxTimeControlEntryCount = _preferences->getUInt(preference_lock_max_timecontrol_entry_count);
|
||||
_maxAuthEntryCount = _preferences->getUInt(preference_lock_max_auth_entry_count);
|
||||
_maxKeypadCodeCount = _preferences->getUInt(keypadMaxCountPreferenceKey());
|
||||
_maxTimeControlEntryCount = _preferences->getUInt(timeControlMaxCountPreferenceKey());
|
||||
_maxAuthEntryCount = _preferences->getUInt(authMaxCountPreferenceKey());
|
||||
_restartBeaconTimeout = _preferences->getInt(preference_restart_ble_beacon_lost);
|
||||
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries, 200);
|
||||
_retryDelay = _preferences->getInt(preference_command_retry_delay);
|
||||
@@ -487,7 +511,7 @@ void NukiWrapper::lockngounlatch()
|
||||
|
||||
const bool NukiWrapper::isPinValid()
|
||||
{
|
||||
return _preferences->getInt(preference_lock_pin_status, (int)NukiPinState::NotConfigured) == (int)NukiPinState::Valid;
|
||||
return _preferences->getInt(pinStatusPreferenceKey(), (int)NukiPinState::NotConfigured) == (int)NukiPinState::Valid;
|
||||
}
|
||||
|
||||
void NukiWrapper::setPin(const uint16_t pin)
|
||||
@@ -513,15 +537,15 @@ const uint32_t NukiWrapper::getUltraPin()
|
||||
void NukiWrapper::unpair()
|
||||
{
|
||||
_nukiLock.unPairNuki();
|
||||
_preferences->remove(preference_lock_log_num);
|
||||
_preferences->remove(lockLogPreferenceKey());
|
||||
Preferences nukiBlePref;
|
||||
nukiBlePref.begin("NukiHub", false);
|
||||
nukiBlePref.begin(_deviceName.c_str(), false);
|
||||
nukiBlePref.clear();
|
||||
nukiBlePref.end();
|
||||
_deviceId->assignNewId();
|
||||
if (!_forceId)
|
||||
{
|
||||
_preferences->remove(preference_nuki_id_lock);
|
||||
_preferences->remove(nukiIdPreferenceKey());
|
||||
}
|
||||
_paired = false;
|
||||
}
|
||||
@@ -643,7 +667,7 @@ void NukiWrapper::updateConfig()
|
||||
|
||||
if(_nukiConfigValid)
|
||||
{
|
||||
if(!_forceId && (_preferences->getUInt(preference_nuki_id_lock, 0) == 0 || _retryConfigCount == 10))
|
||||
if(!_forceId && (_preferences->getUInt(nukiIdPreferenceKey(), 0) == 0 || _retryConfigCount == 10))
|
||||
{
|
||||
char uidString[20];
|
||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
||||
@@ -652,10 +676,10 @@ void NukiWrapper::updateConfig()
|
||||
Log->print(" / ");
|
||||
Log->print(uidString);
|
||||
Log->println(")");
|
||||
_preferences->putUInt(preference_nuki_id_lock, _nukiConfig.nukiId);
|
||||
_preferences->putUInt(nukiIdPreferenceKey(), _nukiConfig.nukiId);
|
||||
}
|
||||
|
||||
if(_preferences->getUInt(preference_nuki_id_lock, 0) == _nukiConfig.nukiId)
|
||||
if(_preferences->getUInt(nukiIdPreferenceKey(), 0) == _nukiConfig.nukiId)
|
||||
{
|
||||
_hasKeypad = _nukiConfig.hasKeypad == 1 || _nukiConfig.hasKeypadV2 == 1;
|
||||
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
|
||||
@@ -673,7 +697,7 @@ void NukiWrapper::updateConfig()
|
||||
updateAuth(false);
|
||||
}
|
||||
|
||||
const int pinStatus = _preferences->getInt(preference_lock_pin_status, (int)NukiPinState::NotConfigured);
|
||||
const int pinStatus = _preferences->getInt(pinStatusPreferenceKey(), (int)NukiPinState::NotConfigured);
|
||||
|
||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||
|
||||
@@ -687,7 +711,7 @@ void NukiWrapper::updateConfig()
|
||||
Log->println("Nuki Lock PIN is invalid or not set");
|
||||
if(pinStatus != 2)
|
||||
{
|
||||
_preferences->putInt(preference_lock_pin_status, (int)NukiPinState::Invalid);
|
||||
_preferences->putInt(pinStatusPreferenceKey(), (int)NukiPinState::Invalid);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -695,7 +719,7 @@ void NukiWrapper::updateConfig()
|
||||
Log->println("Nuki Lock PIN is valid");
|
||||
if(pinStatus != 1)
|
||||
{
|
||||
_preferences->putInt(preference_lock_pin_status, (int)NukiPinState::Valid);
|
||||
_preferences->putInt(pinStatusPreferenceKey(), (int)NukiPinState::Valid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1048,7 @@ void NukiWrapper::updateKeypad(bool retrieved)
|
||||
if(keypadCount > _maxKeypadCodeCount)
|
||||
{
|
||||
_maxKeypadCodeCount = keypadCount;
|
||||
_preferences->putUInt(preference_lock_max_keypad_code_count, _maxKeypadCodeCount);
|
||||
_preferences->putUInt(keypadMaxCountPreferenceKey(), _maxKeypadCodeCount);
|
||||
}
|
||||
|
||||
_network->publishKeypad(entries, _maxKeypadCodeCount);
|
||||
@@ -1094,7 +1118,7 @@ void NukiWrapper::updateTimeControl(bool retrieved)
|
||||
if(timeControlCount > _maxTimeControlEntryCount)
|
||||
{
|
||||
_maxTimeControlEntryCount = timeControlCount;
|
||||
_preferences->putUInt(preference_lock_max_timecontrol_entry_count, _maxTimeControlEntryCount);
|
||||
_preferences->putUInt(timeControlMaxCountPreferenceKey(), _maxTimeControlEntryCount);
|
||||
}
|
||||
|
||||
_network->publishTimeControl(timeControlEntries, _maxTimeControlEntryCount);
|
||||
@@ -1161,7 +1185,7 @@ void NukiWrapper::updateAuth(bool retrieved)
|
||||
if(authCount > _maxAuthEntryCount)
|
||||
{
|
||||
_maxAuthEntryCount = authCount;
|
||||
_preferences->putUInt(preference_lock_max_auth_entry_count, _maxAuthEntryCount);
|
||||
_preferences->putUInt(authMaxCountPreferenceKey(), _maxAuthEntryCount);
|
||||
}
|
||||
|
||||
_network->publishAuth(authEntries, _maxAuthEntryCount);
|
||||
@@ -1182,11 +1206,6 @@ void NukiWrapper::postponeBleWatchdog()
|
||||
_disableBleWatchdogTs = espMillis() + 15000;
|
||||
}
|
||||
|
||||
LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value)
|
||||
{
|
||||
return nukiInst->onLockActionReceived(value);
|
||||
}
|
||||
|
||||
LockActionResult NukiWrapper::onLockActionReceived(const char *value)
|
||||
{
|
||||
NukiLock::LockAction action;
|
||||
@@ -1218,7 +1237,7 @@ LockActionResult NukiWrapper::onLockActionReceived(const char *value)
|
||||
{
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->_nextLockAction = action;
|
||||
_nextLockAction = action;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1233,7 +1252,7 @@ LockActionResult NukiWrapper::onLockActionReceived(const char *value)
|
||||
}
|
||||
else
|
||||
{
|
||||
nukiInst->_nextLockAction = action;
|
||||
_nextLockAction = action;
|
||||
}
|
||||
}
|
||||
return LockActionResult::Success;
|
||||
@@ -1242,16 +1261,6 @@ LockActionResult NukiWrapper::onLockActionReceived(const char *value)
|
||||
return LockActionResult::AccessDenied;
|
||||
}
|
||||
|
||||
void NukiWrapper::onOfficialUpdateReceivedCallback(const char *topic, const char *value)
|
||||
{
|
||||
nukiInst->onOfficialUpdateReceived(topic, value);
|
||||
}
|
||||
|
||||
void NukiWrapper::onConfigUpdateReceivedCallback(const char *value)
|
||||
{
|
||||
nukiInst->onConfigUpdateReceived(value);
|
||||
}
|
||||
|
||||
const bool NukiWrapper::offConnected()
|
||||
{
|
||||
return _nukiOfficial->getOffConnected();
|
||||
@@ -2285,32 +2294,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
void NukiWrapper::onKeypadCommandReceivedCallback(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
|
||||
{
|
||||
nukiInst->onKeypadCommandReceived(command, id, name, code, enabled);
|
||||
}
|
||||
|
||||
void NukiWrapper::onKeypadJsonCommandReceivedCallback(const char *value)
|
||||
{
|
||||
nukiInst->onKeypadJsonCommandReceived(value);
|
||||
}
|
||||
|
||||
void NukiWrapper::onTimeControlCommandReceivedCallback(const char *value)
|
||||
{
|
||||
nukiInst->onTimeControlCommandReceived(value);
|
||||
}
|
||||
|
||||
void NukiWrapper::onAuthCommandReceivedCallback(const char *value)
|
||||
{
|
||||
nukiInst->onAuthCommandReceived(value);
|
||||
}
|
||||
|
||||
|
||||
void NukiWrapper::gpioActionCallback(const GpioAction &action, const int& pin)
|
||||
{
|
||||
nukiInst->onGpioActionReceived(action, pin);
|
||||
}
|
||||
|
||||
void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
{
|
||||
switch(action)
|
||||
@@ -2318,7 +2301,7 @@ void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
case GpioAction::Lock:
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->lock();
|
||||
lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2330,7 +2313,7 @@ void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
case GpioAction::Unlock:
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->unlock();
|
||||
unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2342,7 +2325,7 @@ void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
case GpioAction::Unlatch:
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->unlatch();
|
||||
unlatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2354,7 +2337,7 @@ void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
case GpioAction::LockNgo:
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->lockngo();
|
||||
lockngo();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2366,7 +2349,7 @@ void NukiWrapper::onGpioActionReceived(const GpioAction &action, const int &pin)
|
||||
case GpioAction::LockNgoUnlatch:
|
||||
if(!_nukiOfficial->getOffConnected())
|
||||
{
|
||||
nukiInst->lockngounlatch();
|
||||
lockngounlatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3997,7 +3980,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
||||
}
|
||||
else if(eventType == Nuki::EventType::ERROR_BAD_PIN)
|
||||
{
|
||||
_preferences->putInt(preference_lock_pin_status, (int)NukiPinState::Invalid);
|
||||
_preferences->putInt(pinStatusPreferenceKey(), (int)NukiPinState::Invalid);
|
||||
}
|
||||
else if(eventType == Nuki::EventType::BLE_ERROR_ON_DISCONNECT)
|
||||
{
|
||||
@@ -4116,4 +4099,82 @@ void NukiWrapper::updateTime()
|
||||
{
|
||||
return _nukiLock.updateTime(nukiTime);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::nukiIdPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_nuki_id_lock_2;
|
||||
case 3:
|
||||
return preference_nuki_id_lock_3;
|
||||
default:
|
||||
return preference_nuki_id_lock;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::pinStatusPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_lock_pin_status_2;
|
||||
case 3:
|
||||
return preference_lock_pin_status_3;
|
||||
default:
|
||||
return preference_lock_pin_status;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::keypadMaxCountPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_lock_max_keypad_code_count_2;
|
||||
case 3:
|
||||
return preference_lock_max_keypad_code_count_3;
|
||||
default:
|
||||
return preference_lock_max_keypad_code_count;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::timeControlMaxCountPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_lock_max_timecontrol_entry_count_2;
|
||||
case 3:
|
||||
return preference_lock_max_timecontrol_entry_count_3;
|
||||
default:
|
||||
return preference_lock_max_timecontrol_entry_count;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::authMaxCountPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_lock_max_auth_entry_count_2;
|
||||
case 3:
|
||||
return preference_lock_max_auth_entry_count_3;
|
||||
default:
|
||||
return preference_lock_max_auth_entry_count;
|
||||
}
|
||||
}
|
||||
|
||||
const char* NukiWrapper::lockLogPreferenceKey() const
|
||||
{
|
||||
switch(_lockSlot)
|
||||
{
|
||||
case 2:
|
||||
return preference_lock_log_num_2;
|
||||
case 3:
|
||||
return preference_lock_log_num_3;
|
||||
default:
|
||||
return preference_lock_log_num;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
class NukiWrapper : public Nuki::SmartlockEventHandler
|
||||
{
|
||||
public:
|
||||
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize);
|
||||
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize, uint8_t lockSlot = 1);
|
||||
virtual ~NukiWrapper();
|
||||
|
||||
void initialize();
|
||||
@@ -53,14 +53,6 @@ public:
|
||||
void notify(Nuki::EventType eventType) override;
|
||||
|
||||
private:
|
||||
static LockActionResult onLockActionReceivedCallback(const char* value);
|
||||
static void onOfficialUpdateReceivedCallback(const char* topic, const char* value);
|
||||
static void onConfigUpdateReceivedCallback(const char* value);
|
||||
static void onKeypadCommandReceivedCallback(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
|
||||
static void onKeypadJsonCommandReceivedCallback(const char* value);
|
||||
static void onTimeControlCommandReceivedCallback(const char* value);
|
||||
static void onAuthCommandReceivedCallback(const char* value);
|
||||
static void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||
LockActionResult onLockActionReceived(const char* value);
|
||||
void onKeypadCommandReceived(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
|
||||
void onOfficialUpdateReceived(const char* topic, const char* value);
|
||||
@@ -85,6 +77,12 @@ private:
|
||||
|
||||
void readConfig();
|
||||
void readAdvancedConfig();
|
||||
const char* nukiIdPreferenceKey() const;
|
||||
const char* pinStatusPreferenceKey() const;
|
||||
const char* keypadMaxCountPreferenceKey() const;
|
||||
const char* timeControlMaxCountPreferenceKey() const;
|
||||
const char* authMaxCountPreferenceKey() const;
|
||||
const char* lockLogPreferenceKey() const;
|
||||
|
||||
std::string _deviceName;
|
||||
NukiDeviceId* _deviceId = nullptr;
|
||||
@@ -167,6 +165,7 @@ private:
|
||||
std::string _firmwareVersion = "";
|
||||
std::string _hardwareVersion = "";
|
||||
volatile NukiLock::LockAction _nextLockAction = (NukiLock::LockAction)0xff;
|
||||
uint8_t _lockSlot = 1;
|
||||
|
||||
char* _buffer;
|
||||
const size_t _bufferSize;
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
|
||||
//REQUIRE SERVICES RELOAD
|
||||
#define preference_lock_enabled (char*)"lockena"
|
||||
#define preference_lock_enabled_2 (char*)"lockena2"
|
||||
#define preference_lock_enabled_3 (char*)"lockena3"
|
||||
#define preference_opener_enabled (char*)"openerena"
|
||||
#define preference_debug_connect (char*)"dbgConnect"
|
||||
#define preference_debug_communication (char*)"dbgCommu"
|
||||
@@ -145,6 +147,9 @@
|
||||
#define preference_mqtt_user (char*)"mqttuser"
|
||||
#define preference_mqtt_password (char*)"mqttpass"
|
||||
#define preference_mqtt_lock_path (char*)"mqttpath"
|
||||
#define preference_mqtt_lock_name_1 (char*)"mqttlcknm1"
|
||||
#define preference_mqtt_lock_name_2 (char*)"mqttlcknm2"
|
||||
#define preference_mqtt_lock_name_3 (char*)"mqttlcknm3"
|
||||
#define preference_mqtt_hass_enabled (char*)"hassena"
|
||||
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
|
||||
#define preference_disable_non_json (char*)"disnonjson"
|
||||
@@ -170,23 +175,37 @@
|
||||
#define preference_updater_build (char*)"updBuild"
|
||||
#define preference_updater_date (char*)"updDate"
|
||||
#define preference_lock_max_auth_entry_count (char*)"maxauth"
|
||||
#define preference_lock_max_auth_entry_count_2 (char*)"maxauth2"
|
||||
#define preference_lock_max_auth_entry_count_3 (char*)"maxauth3"
|
||||
#define preference_opener_max_auth_entry_count (char*)"opmaxauth"
|
||||
#define preference_started_before (char*)"run"
|
||||
#define preference_config_version (char*)"confVersion"
|
||||
#define preference_device_id_lock (char*)"deviceId"
|
||||
#define preference_device_id_lock_2 (char*)"deviceId2"
|
||||
#define preference_device_id_lock_3 (char*)"deviceId3"
|
||||
#define preference_device_id_opener (char*)"deviceIdOp"
|
||||
#define preference_nuki_id_lock (char*)"nukiId"
|
||||
#define preference_nuki_id_lock_2 (char*)"nukiId2"
|
||||
#define preference_nuki_id_lock_3 (char*)"nukiId3"
|
||||
#define preference_nuki_id_opener (char*)"nukidOp"
|
||||
#define preference_lock_pin_status (char*)"lockpin"
|
||||
#define preference_lock_pin_status_2 (char*)"lockpin2"
|
||||
#define preference_lock_pin_status_3 (char*)"lockpin3"
|
||||
#define preference_opener_pin_status (char*)"openerpin"
|
||||
#define preference_lock_max_keypad_code_count (char*)"maxkpad"
|
||||
#define preference_lock_max_keypad_code_count_2 (char*)"maxkpad2"
|
||||
#define preference_lock_max_keypad_code_count_3 (char*)"maxkpad3"
|
||||
#define preference_opener_max_keypad_code_count (char*)"opmaxkpad"
|
||||
#define preference_lock_max_timecontrol_entry_count (char*)"maxtc"
|
||||
#define preference_lock_max_timecontrol_entry_count_2 (char*)"maxtc2"
|
||||
#define preference_lock_max_timecontrol_entry_count_3 (char*)"maxtc3"
|
||||
#define preference_opener_max_timecontrol_entry_count (char*)"opmaxtc"
|
||||
#define preference_latest_version (char*)"latest"
|
||||
#define preference_reset_mqtt_topics (char*)"rstMqtt"
|
||||
#define preference_nukihub_id (char*)"nukihubId"
|
||||
#define preference_lock_log_num (char*)"lckLgNm"
|
||||
#define preference_lock_log_num_2 (char*)"lckLgNm2"
|
||||
#define preference_lock_log_num_3 (char*)"lckLgNm3"
|
||||
#define preference_opener_log_num (char*)"opLgNm"
|
||||
|
||||
//OBSOLETE
|
||||
@@ -206,6 +225,8 @@ inline void initPreferences(Preferences* preferences)
|
||||
|
||||
preferences->putBool(preference_started_before, true);
|
||||
preferences->putBool(preference_lock_enabled, true);
|
||||
preferences->putBool(preference_lock_enabled_2, false);
|
||||
preferences->putBool(preference_lock_enabled_3, false);
|
||||
uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
preferences->putBytes(preference_acl, (byte*)(&aclPrefs), sizeof(aclPrefs));
|
||||
uint32_t basicLockConfigAclPrefs[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
@@ -218,6 +239,9 @@ inline void initPreferences(Preferences* preferences)
|
||||
preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
|
||||
preferences->putString(preference_mqtt_lock_path, "nukihub");
|
||||
preferences->putString(preference_mqtt_lock_name_1, "lock");
|
||||
preferences->putString(preference_mqtt_lock_name_2, "lock2");
|
||||
preferences->putString(preference_mqtt_lock_name_3, "lock3");
|
||||
preferences->putString(preference_time_server, "pool.ntp.org");
|
||||
preferences->putString(preference_cred_duo_host, "");
|
||||
preferences->putString(preference_cred_duo_ikey, "");
|
||||
@@ -536,11 +560,11 @@ class DebugPreferences
|
||||
private:
|
||||
std::vector<char*> _keys =
|
||||
{
|
||||
preference_started_before, preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener,
|
||||
preference_started_before, preference_config_version, preference_device_id_lock, preference_device_id_lock_2, preference_device_id_lock_3, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_lock_2, preference_nuki_id_lock_3, preference_nuki_id_opener,
|
||||
preference_mqtt_broker, preference_mqtt_broker_port, preference_mqtt_user, preference_mqtt_password, preference_mqtt_log_enabled, preference_check_updates,
|
||||
preference_webserver_enabled, preference_lock_enabled, preference_lock_pin_status, preference_mqtt_lock_path, preference_opener_enabled, preference_opener_pin_status,
|
||||
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_update_time, preference_time_server,
|
||||
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset,
|
||||
preference_webserver_enabled, preference_lock_enabled, preference_lock_enabled_2, preference_lock_enabled_3, preference_lock_pin_status, preference_lock_pin_status_2, preference_lock_pin_status_3, preference_mqtt_lock_path, preference_mqtt_lock_name_1, preference_mqtt_lock_name_2, preference_mqtt_lock_name_3, preference_opener_enabled, preference_opener_pin_status,
|
||||
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_lock_max_keypad_code_count_2, preference_lock_max_keypad_code_count_3, preference_opener_max_keypad_code_count, preference_update_time, preference_time_server,
|
||||
preference_lock_max_timecontrol_entry_count, preference_lock_max_timecontrol_entry_count_2, preference_lock_max_timecontrol_entry_count_3, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset,
|
||||
preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
|
||||
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_http_auth_type, preference_lock_gemini_pin,
|
||||
preference_rssi_publish_interval, preference_hostname, preference_network_timeout, preference_restart_on_disconnect, preference_hybrid_reboot_on_disconnect,
|
||||
@@ -554,7 +578,7 @@ private:
|
||||
preference_update_from_mqtt, preference_show_secrets, preference_ble_tx_power, preference_webserial_enabled, preference_find_best_rssi, preference_lock_gemini_enabled,
|
||||
preference_network_custom_mdc, preference_network_custom_clk, preference_network_custom_phy, preference_network_custom_addr, preference_network_custom_irq,
|
||||
preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi,
|
||||
preference_network_custom_pwr, preference_network_custom_mdio, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count,
|
||||
preference_network_custom_pwr, preference_network_custom_mdio, preference_lock_max_auth_entry_count, preference_lock_max_auth_entry_count_2, preference_lock_max_auth_entry_count_3, preference_opener_max_auth_entry_count,
|
||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_wifi_ssid, preference_wifi_pass,
|
||||
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled, preference_hass_device_discovery, preference_retain_gpio,
|
||||
preference_debug_connect, preference_debug_communication, preference_debug_readable_data, preference_debug_hex_data, preference_debug_command,
|
||||
@@ -567,13 +591,13 @@ private:
|
||||
};
|
||||
std::vector<char*> _redact =
|
||||
{
|
||||
preference_mqtt_user, preference_mqtt_password, preference_cred_user, preference_cred_password, preference_nuki_id_lock, preference_nuki_id_opener, preference_wifi_pass,
|
||||
preference_mqtt_user, preference_mqtt_password, preference_cred_user, preference_cred_password, preference_nuki_id_lock, preference_nuki_id_lock_2, preference_nuki_id_lock_3, preference_nuki_id_opener, preference_wifi_pass,
|
||||
preference_lock_gemini_pin, preference_cred_duo_host, preference_cred_duo_ikey, preference_cred_duo_skey, preference_cred_duo_user, preference_bypass_proxy,
|
||||
preference_totp_secret, preference_bypass_secret, preference_admin_secret
|
||||
};
|
||||
std::vector<char*> _boolPrefs =
|
||||
{
|
||||
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
|
||||
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_lock_enabled_2, preference_lock_enabled_3, preference_opener_enabled, preference_opener_continuous_mode,
|
||||
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled, preference_update_time,
|
||||
preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_show_secrets,
|
||||
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
|
||||
@@ -594,8 +618,8 @@ private:
|
||||
std::vector<char*> _intPrefs =
|
||||
{
|
||||
preference_config_version, preference_mqtt_broker_port, preference_command_retry_delay, preference_query_interval_hybrid_lockstate,
|
||||
preference_lock_pin_status, preference_opener_pin_status, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
|
||||
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_buffer_size, preference_network_hardware,
|
||||
preference_lock_pin_status, preference_lock_pin_status_2, preference_lock_pin_status_3, preference_opener_pin_status, preference_lock_max_keypad_code_count, preference_lock_max_keypad_code_count_2, preference_lock_max_keypad_code_count_3, preference_opener_max_keypad_code_count,
|
||||
preference_lock_max_timecontrol_entry_count, preference_lock_max_timecontrol_entry_count_2, preference_lock_max_timecontrol_entry_count_3, preference_opener_max_timecontrol_entry_count, preference_buffer_size, preference_network_hardware,
|
||||
preference_rssi_publish_interval, preference_network_timeout, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
|
||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_command_nr_of_retries,
|
||||
preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries,
|
||||
@@ -608,7 +632,7 @@ private:
|
||||
};
|
||||
std::vector<char*> _uintPrefs =
|
||||
{
|
||||
preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener
|
||||
preference_device_id_lock, preference_device_id_lock_2, preference_device_id_lock_3, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_lock_2, preference_nuki_id_lock_3, preference_nuki_id_opener
|
||||
};
|
||||
std::vector<char*> _uint64Prefs =
|
||||
{
|
||||
@@ -643,4 +667,4 @@ public:
|
||||
{
|
||||
return _uint64Prefs;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,6 +24,33 @@ extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_
|
||||
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end");
|
||||
extern bool timeSynced;
|
||||
|
||||
static bool isValidMqttLockName(const String& value)
|
||||
{
|
||||
if(value.length() < 3 || value.length() > 32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < value.length(); i++)
|
||||
{
|
||||
const char c = value.charAt(i);
|
||||
if((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static String normalizeMqttLockName(String value)
|
||||
{
|
||||
value.trim();
|
||||
value.toLowerCase();
|
||||
return value;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE) || defined(CONFIG_ESP_WIFI_REMOTE_ENABLED)
|
||||
#include "esp_hosted.h"
|
||||
static esp_hosted_coprocessor_fwver_t slave_version_struct = {
|
||||
@@ -43,6 +70,8 @@ static esp_hosted_coprocessor_fwver_t host_version_struct = {
|
||||
#include <NetworkClientSecure.h>
|
||||
#include "ArduinoJson.h"
|
||||
#include <freertos/queue.h>
|
||||
extern NukiWrapper* nuki2;
|
||||
extern NukiWrapper* nuki3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -1341,11 +1370,19 @@ void WebCfgServer::initialize()
|
||||
}
|
||||
else if (value == "unpairlock")
|
||||
{
|
||||
return processUnpair(request, resp, false);
|
||||
return processUnpair(request, resp, false, 1);
|
||||
}
|
||||
else if (value == "unpairlock2")
|
||||
{
|
||||
return processUnpair(request, resp, false, 2);
|
||||
}
|
||||
else if (value == "unpairlock3")
|
||||
{
|
||||
return processUnpair(request, resp, false, 3);
|
||||
}
|
||||
else if (value == "unpairopener")
|
||||
{
|
||||
return processUnpair(request, resp, true);
|
||||
return processUnpair(request, resp, true, 1);
|
||||
}
|
||||
else if (value == "factoryreset")
|
||||
{
|
||||
@@ -2894,6 +2931,43 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
else if(key == "MQTTLOCKNAME1" || key == "MQTTLOCKNAME2" || key == "MQTTLOCKNAME3")
|
||||
{
|
||||
value = normalizeMqttLockName(value);
|
||||
if(!isValidMqttLockName(value))
|
||||
{
|
||||
message = "Invalid MQTT lock name. Allowed: a-z, 0-9, _ and -, length 3..32.";
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* prefKey = preference_mqtt_lock_name_1;
|
||||
if(key == "MQTTLOCKNAME2")
|
||||
{
|
||||
prefKey = preference_mqtt_lock_name_2;
|
||||
}
|
||||
else if(key == "MQTTLOCKNAME3")
|
||||
{
|
||||
prefKey = preference_mqtt_lock_name_3;
|
||||
}
|
||||
|
||||
if(_preferences->getString(prefKey, "") != value)
|
||||
{
|
||||
const String n1 = (key == "MQTTLOCKNAME1") ? value : normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_1, "lock"));
|
||||
const String n2 = (key == "MQTTLOCKNAME2") ? value : normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_2, "lock2"));
|
||||
const String n3 = (key == "MQTTLOCKNAME3") ? value : normalizeMqttLockName(_preferences->getString(preference_mqtt_lock_name_3, "lock3"));
|
||||
|
||||
if(n1 == n2 || n1 == n3 || n2 == n3)
|
||||
{
|
||||
message = "Duplicate MQTT lock name is not allowed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
_preferences->putString(prefKey, value);
|
||||
Log->print("Setting changed: ");
|
||||
Log->println(key);
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
else if(key == "MQTTCA")
|
||||
{
|
||||
if (!SPIFFS.begin(true))
|
||||
@@ -4669,6 +4743,26 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
else if(key == "LOCKENA2")
|
||||
{
|
||||
if(_preferences->getBool(preference_lock_enabled_2, false) != (value == "1"))
|
||||
{
|
||||
_preferences->putBool(preference_lock_enabled_2, (value == "1"));
|
||||
Log->print("Setting changed: ");
|
||||
Log->println(key);
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
else if(key == "LOCKENA3")
|
||||
{
|
||||
if(_preferences->getBool(preference_lock_enabled_3, false) != (value == "1"))
|
||||
{
|
||||
_preferences->putBool(preference_lock_enabled_3, (value == "1"));
|
||||
Log->print("Setting changed: ");
|
||||
Log->println(key);
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
else if(key == "GEMINIENA")
|
||||
{
|
||||
if(_preferences->getBool(preference_lock_gemini_enabled, false) != (value == "1"))
|
||||
@@ -5051,6 +5145,15 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S
|
||||
_preferences->putBool(preference_mfa_reconfigure, true);
|
||||
}
|
||||
|
||||
if(_preferences->getBool(preference_lock_enabled_2, false) || _preferences->getBool(preference_lock_enabled_3, false))
|
||||
{
|
||||
if(_preferences->getBool(preference_opener_enabled, false))
|
||||
{
|
||||
_preferences->putBool(preference_opener_enabled, false);
|
||||
restartServicesReconnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(configChanged)
|
||||
{
|
||||
message = "Configuration saved, reboot required to apply some settings";
|
||||
@@ -5106,7 +5209,12 @@ bool WebCfgServer::processImport(PsychicRequest *request, PsychicResponse* resp,
|
||||
return configChanged;
|
||||
}
|
||||
|
||||
_importExport->importJson(doc);
|
||||
JsonDocument importResult = _importExport->importJson(doc);
|
||||
if(!importResult["_import_error"].isNull())
|
||||
{
|
||||
message = importResult["_import_error"].as<String>();
|
||||
return false;
|
||||
}
|
||||
|
||||
configChanged = true;
|
||||
}
|
||||
@@ -5427,6 +5535,32 @@ esp_err_t WebCfgServer::buildCredHtml(PsychicRequest *request, PsychicResponse*
|
||||
response.print("</table>");
|
||||
response.print("<br><button type=\"submit\">OK</button></form>");
|
||||
}
|
||||
if(_preferences->getBool(preference_lock_enabled_2, false))
|
||||
{
|
||||
response.print("<br><br><h3>Unpair Nuki Lock Slot 2</h3>");
|
||||
response.print("<form class=\"adapt\" method=\"post\" action=\"/post\">");
|
||||
response.print("<input type=\"hidden\" name=\"page\" value=\"unpairlock2\">");
|
||||
response.print("<table>");
|
||||
String message = "Type ";
|
||||
message.concat(_confirmCode);
|
||||
message.concat(" to confirm unpair");
|
||||
printInputField(&response, "CONFIRMTOKEN", message.c_str(), "", 10, "");
|
||||
response.print("</table>");
|
||||
response.print("<br><button type=\"submit\">OK</button></form>");
|
||||
}
|
||||
if(_preferences->getBool(preference_lock_enabled_3, false))
|
||||
{
|
||||
response.print("<br><br><h3>Unpair Nuki Lock Slot 3</h3>");
|
||||
response.print("<form class=\"adapt\" method=\"post\" action=\"/post\">");
|
||||
response.print("<input type=\"hidden\" name=\"page\" value=\"unpairlock3\">");
|
||||
response.print("<table>");
|
||||
String message = "Type ";
|
||||
message.concat(_confirmCode);
|
||||
message.concat(" to confirm unpair");
|
||||
printInputField(&response, "CONFIRMTOKEN", message.c_str(), "", 10, "");
|
||||
response.print("</table>");
|
||||
response.print("<br><button type=\"submit\">OK</button></form>");
|
||||
}
|
||||
if(_nukiOpener != nullptr)
|
||||
{
|
||||
response.print("<br><br><h3>Unpair Nuki Opener</h3>");
|
||||
@@ -5516,6 +5650,9 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request, PsychicResp
|
||||
printInputField(&response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30, "", false, true);
|
||||
printInputField(&response, "MQTTPASS", "MQTT Password", "*", 40, "", true, true);
|
||||
printInputField(&response, "MQTTPATH", "MQTT Nuki Hub Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180, "");
|
||||
printInputField(&response, "MQTTLOCKNAME1", "Lock Slot 1 MQTT Name (a-z,0-9,_,-; 3-32)", _preferences->getString(preference_mqtt_lock_name_1, "lock").c_str(), 32, "");
|
||||
printInputField(&response, "MQTTLOCKNAME2", "Lock Slot 2 MQTT Name (a-z,0-9,_,-; 3-32)", _preferences->getString(preference_mqtt_lock_name_2, "lock2").c_str(), 32, "");
|
||||
printInputField(&response, "MQTTLOCKNAME3", "Lock Slot 3 MQTT Name (a-z,0-9,_,-; 3-32)", _preferences->getString(preference_mqtt_lock_name_3, "lock3").c_str(), 32, "");
|
||||
printCheckBox(&response, "ENHADISC", "Enable Home Assistant auto discovery", _preferences->getBool(preference_mqtt_hass_enabled), "chkHass");
|
||||
response.print("</table><br>");
|
||||
|
||||
@@ -6160,6 +6297,8 @@ esp_err_t WebCfgServer::buildNukiConfigHtml(PsychicRequest *request, PsychicResp
|
||||
response.print("<h3>Basic Nuki Configuration</h3>");
|
||||
response.print("<table>");
|
||||
printCheckBox(&response, "LOCKENA", "Nuki Lock enabled", _preferences->getBool(preference_lock_enabled, true), "");
|
||||
printCheckBox(&response, "LOCKENA2", "Nuki Lock slot 2 enabled", _preferences->getBool(preference_lock_enabled_2, false), "");
|
||||
printCheckBox(&response, "LOCKENA3", "Nuki Lock slot 3 enabled", _preferences->getBool(preference_lock_enabled_3, false), "");
|
||||
printCheckBox(&response, "GEMINIENA", "Nuki Smartlock Ultra/Go/5th gen enabled", _preferences->getBool(preference_lock_gemini_enabled, false), "");
|
||||
printCheckBox(&response, "OPENA", "Nuki Opener enabled", _preferences->getBool(preference_opener_enabled, false), "");
|
||||
response.print("</table><br>");
|
||||
@@ -6865,6 +7004,42 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request, PsychicResponse*
|
||||
}
|
||||
}
|
||||
|
||||
response.print("\n\n------------ NUKI LOCK SLOT 2 ------------");
|
||||
response.print("\nEnabled: ");
|
||||
response.print(_preferences->getBool(preference_lock_enabled_2, false) ? "Yes" : "No");
|
||||
response.print("\nMQTT name: ");
|
||||
response.print(_preferences->getString(preference_mqtt_lock_name_2, "lock2"));
|
||||
response.print("\nNuki Hub device ID: ");
|
||||
response.print(_preferences->getUInt(preference_device_id_lock_2, 0));
|
||||
response.print("\nNuki device ID: ");
|
||||
response.print(_preferences->getUInt(preference_nuki_id_lock_2, 0) > 0 ? "***" : "Not set");
|
||||
response.print("\nValid PIN set: ");
|
||||
response.print(pinStateToString((NukiPinState)_preferences->getInt(preference_lock_pin_status_2, (int)NukiPinState::NotConfigured)));
|
||||
response.print("\nKeypad highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_keypad_code_count_2, 0));
|
||||
response.print("\nTimecontrol highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_timecontrol_entry_count_2, 0));
|
||||
response.print("\nAuthorizations highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_auth_entry_count_2, 0));
|
||||
|
||||
response.print("\n\n------------ NUKI LOCK SLOT 3 ------------");
|
||||
response.print("\nEnabled: ");
|
||||
response.print(_preferences->getBool(preference_lock_enabled_3, false) ? "Yes" : "No");
|
||||
response.print("\nMQTT name: ");
|
||||
response.print(_preferences->getString(preference_mqtt_lock_name_3, "lock3"));
|
||||
response.print("\nNuki Hub device ID: ");
|
||||
response.print(_preferences->getUInt(preference_device_id_lock_3, 0));
|
||||
response.print("\nNuki device ID: ");
|
||||
response.print(_preferences->getUInt(preference_nuki_id_lock_3, 0) > 0 ? "***" : "Not set");
|
||||
response.print("\nValid PIN set: ");
|
||||
response.print(pinStateToString((NukiPinState)_preferences->getInt(preference_lock_pin_status_3, (int)NukiPinState::NotConfigured)));
|
||||
response.print("\nKeypad highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_keypad_code_count_3, 0));
|
||||
response.print("\nTimecontrol highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_timecontrol_entry_count_3, 0));
|
||||
response.print("\nAuthorizations highest entries count: ");
|
||||
response.print(_preferences->getInt(preference_lock_max_auth_entry_count_3, 0));
|
||||
|
||||
response.print("\n\n------------ NUKI OPENER ------------");
|
||||
if(_nukiOpener == nullptr || !_preferences->getBool(preference_opener_enabled, false))
|
||||
{
|
||||
@@ -7050,7 +7225,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request, PsychicResponse*
|
||||
return response.endSend();
|
||||
}
|
||||
|
||||
esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, PsychicResponse* resp, bool opener)
|
||||
esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, PsychicResponse* resp, bool opener, uint8_t lockSlot)
|
||||
{
|
||||
String value = "";
|
||||
if(request->hasParam("CONFIRMTOKEN"))
|
||||
@@ -7067,12 +7242,74 @@ esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, PsychicResponse*
|
||||
return buildConfirmHtml(request, resp, "Confirm code is invalid.", 3, true);
|
||||
}
|
||||
|
||||
esp_err_t res = buildConfirmHtml(request, resp, opener ? "Unpairing Nuki Opener." : "Unpairing Nuki Lock.", 3, true);
|
||||
|
||||
if(!opener && _nuki != nullptr)
|
||||
String confirmMsg = opener ? "Unpairing Nuki Opener." : "Unpairing Nuki Lock.";
|
||||
if(!opener && lockSlot == 2)
|
||||
{
|
||||
_nuki->unpair();
|
||||
_preferences->putInt(preference_lock_pin_status, (int)NukiPinState::NotConfigured);
|
||||
confirmMsg = "Unpairing Nuki Lock Slot 2.";
|
||||
}
|
||||
else if(!opener && lockSlot == 3)
|
||||
{
|
||||
confirmMsg = "Unpairing Nuki Lock Slot 3.";
|
||||
}
|
||||
esp_err_t res = buildConfirmHtml(request, resp, confirmMsg, 3, true);
|
||||
|
||||
if(!opener)
|
||||
{
|
||||
auto clearLockSlot = [&](const uint8_t slot)
|
||||
{
|
||||
const char* prefPinKey = preference_lock_pin_status;
|
||||
const char* prefNukiIdKey = preference_nuki_id_lock;
|
||||
const char* prefDeviceIdKey = preference_device_id_lock;
|
||||
const char* prefLogKey = preference_lock_log_num;
|
||||
const char* bleNs = "NukiHub";
|
||||
|
||||
if(slot == 2)
|
||||
{
|
||||
prefPinKey = preference_lock_pin_status_2;
|
||||
prefNukiIdKey = preference_nuki_id_lock_2;
|
||||
prefDeviceIdKey = preference_device_id_lock_2;
|
||||
prefLogKey = preference_lock_log_num_2;
|
||||
bleNs = "NukiHub2";
|
||||
}
|
||||
else if(slot == 3)
|
||||
{
|
||||
prefPinKey = preference_lock_pin_status_3;
|
||||
prefNukiIdKey = preference_nuki_id_lock_3;
|
||||
prefDeviceIdKey = preference_device_id_lock_3;
|
||||
prefLogKey = preference_lock_log_num_3;
|
||||
bleNs = "NukiHub3";
|
||||
}
|
||||
|
||||
Preferences nukiBlePref;
|
||||
nukiBlePref.begin(bleNs, false);
|
||||
nukiBlePref.clear();
|
||||
nukiBlePref.end();
|
||||
|
||||
_preferences->remove(prefLogKey);
|
||||
_preferences->remove(prefNukiIdKey);
|
||||
_preferences->putInt(prefPinKey, (int)NukiPinState::NotConfigured);
|
||||
_preferences->putUInt(prefDeviceIdKey, esp_random());
|
||||
};
|
||||
|
||||
if(lockSlot == 1 && _nuki != nullptr)
|
||||
{
|
||||
_nuki->unpair();
|
||||
_preferences->putInt(preference_lock_pin_status, (int)NukiPinState::NotConfigured);
|
||||
}
|
||||
else if(lockSlot == 2 && nuki2 != nullptr)
|
||||
{
|
||||
nuki2->unpair();
|
||||
_preferences->putInt(preference_lock_pin_status_2, (int)NukiPinState::NotConfigured);
|
||||
}
|
||||
else if(lockSlot == 3 && nuki3 != nullptr)
|
||||
{
|
||||
nuki3->unpair();
|
||||
_preferences->putInt(preference_lock_pin_status_3, (int)NukiPinState::NotConfigured);
|
||||
}
|
||||
else
|
||||
{
|
||||
clearLockSlot(lockSlot);
|
||||
}
|
||||
}
|
||||
if(opener && _nukiOpener != nullptr)
|
||||
{
|
||||
@@ -7215,6 +7452,14 @@ esp_err_t WebCfgServer::processFactoryReset(PsychicRequest *request, PsychicResp
|
||||
{
|
||||
_nuki->unpair();
|
||||
}
|
||||
if(nuki2 != nullptr)
|
||||
{
|
||||
nuki2->unpair();
|
||||
}
|
||||
if(nuki3 != nullptr)
|
||||
{
|
||||
nuki3->unpair();
|
||||
}
|
||||
if(_nukiOpener != nullptr)
|
||||
{
|
||||
_nukiOpener->unpair();
|
||||
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
#endif
|
||||
esp_err_t buildInfoHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildCustomNetworkConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t processUnpair(PsychicRequest *request, PsychicResponse* resp, bool opener);
|
||||
esp_err_t processUnpair(PsychicRequest *request, PsychicResponse* resp, bool opener, uint8_t lockSlot = 1);
|
||||
esp_err_t processUpdate(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t processFactoryReset(PsychicRequest *request, PsychicResponse* resp);
|
||||
void printTextarea(PsychicStreamResponse *response, const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false);
|
||||
|
||||
251
src/main.cpp
251
src/main.cpp
@@ -52,22 +52,36 @@ bool nuki_hub_https_server_enabled = false;
|
||||
#include "ImportExport.h"
|
||||
|
||||
NukiNetworkLock* networkLock = nullptr;
|
||||
NukiNetworkLock* networkLock2 = nullptr;
|
||||
NukiNetworkLock* networkLock3 = nullptr;
|
||||
NukiNetworkOpener* networkOpener = nullptr;
|
||||
BleScanner::Scanner* bleScanner = nullptr;
|
||||
NukiWrapper* nuki = nullptr;
|
||||
NukiWrapper* nuki2 = nullptr;
|
||||
NukiWrapper* nuki3 = nullptr;
|
||||
NukiOfficial* nukiOfficial = nullptr;
|
||||
NukiOfficial* nukiOfficial2 = nullptr;
|
||||
NukiOfficial* nukiOfficial3 = nullptr;
|
||||
NukiOpenerWrapper* nukiOpener = nullptr;
|
||||
NukiDeviceId* deviceIdLock = nullptr;
|
||||
NukiDeviceId* deviceIdLock2 = nullptr;
|
||||
NukiDeviceId* deviceIdLock3 = nullptr;
|
||||
NukiDeviceId* deviceIdOpener = nullptr;
|
||||
Gpio* gpio = nullptr;
|
||||
SerialReader* serialReader = nullptr;
|
||||
|
||||
bool bleDone = false;
|
||||
bool lockEnabled = false;
|
||||
bool lockEnabled2 = false;
|
||||
bool lockEnabled3 = false;
|
||||
bool openerEnabled = false;
|
||||
bool wifiConnected = false;
|
||||
bool rebootLock = false;
|
||||
bool rebootLock2 = false;
|
||||
bool rebootLock3 = false;
|
||||
uint8_t lockRestartControllerCount = 0;
|
||||
uint8_t lockRestartControllerCount2 = 0;
|
||||
uint8_t lockRestartControllerCount3 = 0;
|
||||
uint8_t openerRestartControllerCount = 0;
|
||||
char16_t buffer_size = CHAR_BUFFER_SIZE;
|
||||
|
||||
@@ -703,14 +717,33 @@ void startNuki(bool lock)
|
||||
{
|
||||
if (lock)
|
||||
{
|
||||
nukiOfficial = new NukiOfficial(preferences);
|
||||
networkLock = new NukiNetworkLock(network, nukiOfficial, preferences, CharBuffer::get(), buffer_size);
|
||||
|
||||
if(!disableNetwork)
|
||||
if(lockEnabled)
|
||||
{
|
||||
networkLock->initialize();
|
||||
nukiOfficial = new NukiOfficial(preferences);
|
||||
networkLock = new NukiNetworkLock(network, nukiOfficial, preferences, CharBuffer::get(), buffer_size, 1);
|
||||
if(!disableNetwork)
|
||||
{
|
||||
networkLock->initialize();
|
||||
}
|
||||
}
|
||||
if(lockEnabled2)
|
||||
{
|
||||
nukiOfficial2 = new NukiOfficial(preferences);
|
||||
networkLock2 = new NukiNetworkLock(network, nukiOfficial2, preferences, CharBuffer::get(), buffer_size, 2);
|
||||
if(!disableNetwork)
|
||||
{
|
||||
networkLock2->initialize();
|
||||
}
|
||||
}
|
||||
if(lockEnabled3)
|
||||
{
|
||||
nukiOfficial3 = new NukiOfficial(preferences);
|
||||
networkLock3 = new NukiNetworkLock(network, nukiOfficial3, preferences, CharBuffer::get(), buffer_size, 3);
|
||||
if(!disableNetwork)
|
||||
{
|
||||
networkLock3->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
lockStarted = true;
|
||||
}
|
||||
else
|
||||
@@ -730,7 +763,14 @@ void restartServices(bool reconnect)
|
||||
{
|
||||
bleDone = false;
|
||||
lockEnabled = preferences->getBool(preference_lock_enabled);
|
||||
lockEnabled2 = preferences->getBool(preference_lock_enabled_2, false);
|
||||
lockEnabled3 = preferences->getBool(preference_lock_enabled_3, false);
|
||||
openerEnabled = preferences->getBool(preference_opener_enabled);
|
||||
|
||||
if(lockEnabled2 || lockEnabled3)
|
||||
{
|
||||
openerEnabled = false;
|
||||
}
|
||||
importExport->readSettings();
|
||||
network->readSettings();
|
||||
gpio->setPins();
|
||||
@@ -775,13 +815,25 @@ void restartServices(bool reconnect)
|
||||
Log->println("Deleting nuki");
|
||||
delete nuki;
|
||||
nuki = nullptr;
|
||||
delete nuki2;
|
||||
nuki2 = nullptr;
|
||||
delete nuki3;
|
||||
nuki3 = nullptr;
|
||||
if (reconnect)
|
||||
{
|
||||
lockStarted = false;
|
||||
delete networkLock;
|
||||
networkLock = nullptr;
|
||||
delete networkLock2;
|
||||
networkLock2 = nullptr;
|
||||
delete networkLock3;
|
||||
networkLock3 = nullptr;
|
||||
delete nukiOfficial;
|
||||
nukiOfficial = nullptr;
|
||||
delete nukiOfficial2;
|
||||
nukiOfficial2 = nullptr;
|
||||
delete nukiOfficial3;
|
||||
nukiOfficial3 = nullptr;
|
||||
}
|
||||
Log->println("Deleting nuki done");
|
||||
}
|
||||
@@ -830,7 +882,7 @@ void restartServices(bool reconnect)
|
||||
}
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
|
||||
if(lockEnabled || openerEnabled)
|
||||
if(lockEnabled || lockEnabled2 || lockEnabled3 || openerEnabled)
|
||||
{
|
||||
#if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE) || defined(CONFIG_ESP_WIFI_REMOTE_ENABLED)
|
||||
hostedInitBLE();
|
||||
@@ -843,7 +895,7 @@ void restartServices(bool reconnect)
|
||||
Log->println("Restarting BLE Scanner done");
|
||||
}
|
||||
|
||||
if(lockEnabled)
|
||||
if(lockEnabled || lockEnabled2 || lockEnabled3)
|
||||
{
|
||||
Log->println("Restarting Nuki lock");
|
||||
|
||||
@@ -852,9 +904,24 @@ void restartServices(bool reconnect)
|
||||
startNuki(true);
|
||||
}
|
||||
|
||||
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences, CharBuffer::get(), buffer_size);
|
||||
nuki->initialize();
|
||||
bleScanner->whitelist(nuki->getBleAddress());
|
||||
if(lockEnabled && networkLock != nullptr && nukiOfficial != nullptr)
|
||||
{
|
||||
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences, CharBuffer::get(), buffer_size, 1);
|
||||
nuki->initialize();
|
||||
bleScanner->whitelist(nuki->getBleAddress());
|
||||
}
|
||||
if(lockEnabled2 && networkLock2 != nullptr && nukiOfficial2 != nullptr)
|
||||
{
|
||||
nuki2 = new NukiWrapper("NukiHub2", deviceIdLock2, bleScanner, networkLock2, nukiOfficial2, gpio, preferences, CharBuffer::get(), buffer_size, 2);
|
||||
nuki2->initialize();
|
||||
bleScanner->whitelist(nuki2->getBleAddress());
|
||||
}
|
||||
if(lockEnabled3 && networkLock3 != nullptr && nukiOfficial3 != nullptr)
|
||||
{
|
||||
nuki3 = new NukiWrapper("NukiHub3", deviceIdLock3, bleScanner, networkLock3, nukiOfficial3, gpio, preferences, CharBuffer::get(), buffer_size, 3);
|
||||
nuki3->initialize();
|
||||
bleScanner->whitelist(nuki3->getBleAddress());
|
||||
}
|
||||
Log->println("Restarting Nuki lock done");
|
||||
}
|
||||
|
||||
@@ -1014,7 +1081,18 @@ void networkTask(void *pvParameters)
|
||||
|
||||
if(connected && lockStarted)
|
||||
{
|
||||
rebootLock = networkLock->update();
|
||||
if(networkLock != nullptr)
|
||||
{
|
||||
rebootLock = networkLock->update();
|
||||
}
|
||||
if(networkLock2 != nullptr)
|
||||
{
|
||||
rebootLock2 = networkLock2->update();
|
||||
}
|
||||
if(networkLock3 != nullptr)
|
||||
{
|
||||
rebootLock3 = networkLock3->update();
|
||||
}
|
||||
if (esp_task_wdt_status(NULL) == ESP_OK)
|
||||
{
|
||||
esp_task_wdt_reset();
|
||||
@@ -1148,7 +1226,10 @@ void nukiTask(void *pvParameters)
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
bool needsPairing = (lockStarted && !nuki->isPaired()) || (openerStarted && !nukiOpener->isPaired());
|
||||
bool needsPairing = ((lockStarted && nuki != nullptr && !nuki->isPaired()) ||
|
||||
(lockStarted && nuki2 != nullptr && !nuki2->isPaired()) ||
|
||||
(lockStarted && nuki3 != nullptr && !nuki3->isPaired()) ||
|
||||
(openerStarted && !nukiOpener->isPaired()));
|
||||
|
||||
if (needsPairing)
|
||||
{
|
||||
@@ -1161,10 +1242,18 @@ void nukiTask(void *pvParameters)
|
||||
else if (!whiteListed)
|
||||
{
|
||||
whiteListed = true;
|
||||
if(lockEnabled)
|
||||
if(lockEnabled && nuki != nullptr)
|
||||
{
|
||||
bleScanner->whitelist(nuki->getBleAddress());
|
||||
}
|
||||
if(lockEnabled2 && nuki2 != nullptr)
|
||||
{
|
||||
bleScanner->whitelist(nuki2->getBleAddress());
|
||||
}
|
||||
if(lockEnabled3 && nuki3 != nullptr)
|
||||
{
|
||||
bleScanner->whitelist(nuki3->getBleAddress());
|
||||
}
|
||||
if(openerEnabled)
|
||||
{
|
||||
bleScanner->whitelist(nukiOpener->getBleAddress());
|
||||
@@ -1173,35 +1262,104 @@ void nukiTask(void *pvParameters)
|
||||
|
||||
if(lockStarted)
|
||||
{
|
||||
if (nuki->restartController() > 0)
|
||||
if(nuki != nullptr)
|
||||
{
|
||||
if (lockRestartControllerCount > 3)
|
||||
if (nuki->restartController() > 0)
|
||||
{
|
||||
if (nuki->restartController() == 1)
|
||||
if (lockRestartControllerCount > 3)
|
||||
{
|
||||
restartEsp(RestartReason::BLEError);
|
||||
if (nuki->restartController() == 1)
|
||||
{
|
||||
restartEsp(RestartReason::BLEError);
|
||||
}
|
||||
else if (nuki->restartController() == 2)
|
||||
{
|
||||
restartEsp(RestartReason::BLEBeaconWatchdog);
|
||||
}
|
||||
}
|
||||
else if (nuki->restartController() == 2)
|
||||
else
|
||||
{
|
||||
restartEsp(RestartReason::BLEBeaconWatchdog);
|
||||
lockRestartControllerCount += 1;
|
||||
restartServices(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lockRestartControllerCount += 1;
|
||||
restartServices(false);
|
||||
continue;
|
||||
if (lockRestartControllerCount > 0 && nuki->hasConnected())
|
||||
{
|
||||
lockRestartControllerCount = 0;
|
||||
}
|
||||
|
||||
nuki->update(rebootLock);
|
||||
rebootLock = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(nuki2 != nullptr)
|
||||
{
|
||||
if (lockRestartControllerCount > 0 && nuki->hasConnected())
|
||||
if (nuki2->restartController() > 0)
|
||||
{
|
||||
lockRestartControllerCount = 0;
|
||||
if (lockRestartControllerCount2 > 3)
|
||||
{
|
||||
if (nuki2->restartController() == 1)
|
||||
{
|
||||
restartEsp(RestartReason::BLEError);
|
||||
}
|
||||
else if (nuki2->restartController() == 2)
|
||||
{
|
||||
restartEsp(RestartReason::BLEBeaconWatchdog);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lockRestartControllerCount2 += 1;
|
||||
restartServices(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lockRestartControllerCount2 > 0 && nuki2->hasConnected())
|
||||
{
|
||||
lockRestartControllerCount2 = 0;
|
||||
}
|
||||
|
||||
nuki->update(rebootLock);
|
||||
rebootLock = false;
|
||||
nuki2->update(rebootLock2);
|
||||
rebootLock2 = false;
|
||||
}
|
||||
}
|
||||
if(nuki3 != nullptr)
|
||||
{
|
||||
if (nuki3->restartController() > 0)
|
||||
{
|
||||
if (lockRestartControllerCount3 > 3)
|
||||
{
|
||||
if (nuki3->restartController() == 1)
|
||||
{
|
||||
restartEsp(RestartReason::BLEError);
|
||||
}
|
||||
else if (nuki3->restartController() == 2)
|
||||
{
|
||||
restartEsp(RestartReason::BLEBeaconWatchdog);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lockRestartControllerCount3 += 1;
|
||||
restartServices(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lockRestartControllerCount3 > 0 && nuki3->hasConnected())
|
||||
{
|
||||
lockRestartControllerCount3 = 0;
|
||||
}
|
||||
|
||||
nuki3->update(rebootLock3);
|
||||
rebootLock3 = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(openerStarted)
|
||||
@@ -1400,7 +1558,7 @@ void setupTasks(bool ota)
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, (espCores > 1) ? 1 : 0);
|
||||
}
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
if(!network->isApOpen() && (lockEnabled || openerEnabled))
|
||||
if(!network->isApOpen() && (lockEnabled || lockEnabled2 || lockEnabled3 || openerEnabled))
|
||||
{
|
||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 0);
|
||||
}
|
||||
@@ -1702,6 +1860,8 @@ void setup()
|
||||
uint32_t devIdOpener = preferences->getUInt(preference_device_id_opener);
|
||||
|
||||
deviceIdLock = new NukiDeviceId(preferences, preference_device_id_lock);
|
||||
deviceIdLock2 = new NukiDeviceId(preferences, preference_device_id_lock_2);
|
||||
deviceIdLock3 = new NukiDeviceId(preferences, preference_device_id_lock_3);
|
||||
deviceIdOpener = new NukiDeviceId(preferences, preference_device_id_opener);
|
||||
|
||||
if(deviceIdLock->get() != 0 && devIdOpener == 0)
|
||||
@@ -1723,20 +1883,29 @@ void setup()
|
||||
network->initialize();
|
||||
|
||||
lockEnabled = preferences->getBool(preference_lock_enabled);
|
||||
lockEnabled2 = preferences->getBool(preference_lock_enabled_2, false);
|
||||
lockEnabled3 = preferences->getBool(preference_lock_enabled_3, false);
|
||||
openerEnabled = preferences->getBool(preference_opener_enabled);
|
||||
|
||||
if(lockEnabled2 || lockEnabled3)
|
||||
{
|
||||
openerEnabled = false;
|
||||
}
|
||||
|
||||
if(network->isApOpen())
|
||||
{
|
||||
forceEnableWebServer = true;
|
||||
doOta = false;
|
||||
lockEnabled = false;
|
||||
lockEnabled2 = false;
|
||||
lockEnabled3 = false;
|
||||
openerEnabled = false;
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
serialReader = new SerialReader(importExport, network);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(lockEnabled || openerEnabled)
|
||||
if(lockEnabled || lockEnabled2 || lockEnabled3 || openerEnabled)
|
||||
{
|
||||
bleScanner = new BleScanner::Scanner();
|
||||
// Scan interval and window according to Nuki recommendations:
|
||||
@@ -1746,13 +1915,27 @@ void setup()
|
||||
bleScannerStarted = true;
|
||||
}
|
||||
|
||||
Log->println(lockEnabled ? F("Nuki Lock enabled") : F("Nuki Lock disabled"));
|
||||
if(lockEnabled)
|
||||
const bool anyLockEnabled = lockEnabled || lockEnabled2 || lockEnabled3;
|
||||
Log->println(anyLockEnabled ? F("Nuki Lock enabled") : F("Nuki Lock disabled"));
|
||||
if(anyLockEnabled)
|
||||
{
|
||||
startNuki(true);
|
||||
|
||||
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences, CharBuffer::get(), buffer_size);
|
||||
nuki->initialize();
|
||||
if(lockEnabled && networkLock != nullptr && nukiOfficial != nullptr)
|
||||
{
|
||||
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences, CharBuffer::get(), buffer_size, 1);
|
||||
nuki->initialize();
|
||||
}
|
||||
if(lockEnabled2 && networkLock2 != nullptr && nukiOfficial2 != nullptr)
|
||||
{
|
||||
nuki2 = new NukiWrapper("NukiHub2", deviceIdLock2, bleScanner, networkLock2, nukiOfficial2, gpio, preferences, CharBuffer::get(), buffer_size, 2);
|
||||
nuki2->initialize();
|
||||
}
|
||||
if(lockEnabled3 && networkLock3 != nullptr && nukiOfficial3 != nullptr)
|
||||
{
|
||||
nuki3 = new NukiWrapper("NukiHub3", deviceIdLock3, bleScanner, networkLock3, nukiOfficial3, gpio, preferences, CharBuffer::get(), buffer_size, 3);
|
||||
nuki3->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
Log->println(openerEnabled ? F("Nuki Opener enabled") : F("Nuki Opener disabled"));
|
||||
|
||||
@@ -1,363 +1,344 @@
|
||||
0x2f, 0x2a, 0x0d, 0x0a, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
|
||||
0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x65, 0x73, 0x63, 0x61,
|
||||
0x70, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x0d, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x64, 0x6e, 0x2e, 0x6a, 0x73,
|
||||
0x64, 0x65, 0x6c, 0x69, 0x76, 0x72, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x70, 0x6d, 0x2f, 0x40,
|
||||
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x77, 0x2e, 0x63,
|
||||
0x73, 0x73, 0x40, 0x31, 0x2e, 0x31, 0x2e, 0x32, 0x2f, 0x6e, 0x65, 0x77, 0x2e, 0x6d, 0x69, 0x6e,
|
||||
0x2e, 0x63, 0x73, 0x73, 0x0d, 0x0a, 0x2a, 0x2f, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2a, 0x0d, 0x0a,
|
||||
0x20, 0x2a, 0x20, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x0d, 0x0a, 0x20, 0x2a, 0x20, 0x43, 0x6f,
|
||||
0x6d, 0x70, 0x61, 0x63, 0x74, 0x20, 0x2f, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x66, 0x79, 0x20, 0x74,
|
||||
0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e,
|
||||
0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x0d, 0x0a, 0x20, 0x2a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x20,
|
||||
0x6f, 0x6e, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x74, 0x6f, 0x20, 0x73, 0x72, 0x63, 0x2f, 0x57, 0x65, 0x62, 0x43, 0x66, 0x67, 0x53, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x2e, 0x68, 0x20, 0x61,
|
||||
0x73, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x63, 0x73, 0x73, 0x0d, 0x0a, 0x20, 0x2a, 0x20, 0x54,
|
||||
0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
|
||||
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
|
||||
0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3a, 0x29, 0x0d, 0x0a, 0x2a, 0x2f, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x61, 0x6e, 0x73, 0x3a, 0x20,
|
||||
0x27, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x27, 0x2c, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x73,
|
||||
0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x42, 0x6c, 0x69, 0x6e, 0x6b, 0x4d, 0x61, 0x63, 0x53, 0x79,
|
||||
0x73, 0x74, 0x65, 0x6d, 0x46, 0x6f, 0x6e, 0x74, 0x2c, 0x27, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20,
|
||||
0x55, 0x49, 0x27, 0x2c, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f, 0x2c, 0x4f, 0x78, 0x79, 0x67, 0x65,
|
||||
0x6e, 0x2c, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x2c, 0x43, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65,
|
||||
0x6c, 0x6c, 0x2c, 0x27, 0x4f, 0x70, 0x65, 0x6e, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x27, 0x2c, 0x27,
|
||||
0x48, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x20, 0x4e, 0x65, 0x75, 0x65, 0x27, 0x2c,
|
||||
0x73, 0x61, 0x6e, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x69, 0x66, 0x2c, 0x27, 0x41, 0x70, 0x70, 0x6c,
|
||||
0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x27, 0x2c, 0x27,
|
||||
0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x27, 0x2c,
|
||||
0x27, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
|
||||
0x27, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x66, 0x6f, 0x6e,
|
||||
0x74, 0x2d, 0x6d, 0x6f, 0x6e, 0x6f, 0x3a, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x61, 0x73,
|
||||
0x2c, 0x6d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x2c, 0x27, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x20,
|
||||
0x4d, 0x6f, 0x6e, 0x6f, 0x27, 0x2c, 0x27, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x27, 0x2c, 0x27, 0x43, 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72,
|
||||
0x20, 0x4e, 0x65, 0x77, 0x27, 0x2c, 0x43, 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f,
|
||||
0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x0d, 0x0a,
|
||||
0x2f, 0x2a, 0x0a, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, 0x74,
|
||||
0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x65, 0x73, 0x63, 0x61, 0x70,
|
||||
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x20,
|
||||
0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x64, 0x6e, 0x2e, 0x6a, 0x73, 0x64, 0x65,
|
||||
0x6c, 0x69, 0x76, 0x72, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x70, 0x6d, 0x2f, 0x40, 0x65, 0x78,
|
||||
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x77, 0x2e, 0x63, 0x73, 0x73,
|
||||
0x40, 0x31, 0x2e, 0x31, 0x2e, 0x32, 0x2f, 0x6e, 0x65, 0x77, 0x2e, 0x6d, 0x69, 0x6e, 0x2e, 0x63,
|
||||
0x73, 0x73, 0x0a, 0x2a, 0x2f, 0x0a, 0x0a, 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x55, 0x73, 0x61,
|
||||
0x67, 0x65, 0x3a, 0x0a, 0x20, 0x2a, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x20, 0x2f,
|
||||
0x20, 0x6d, 0x69, 0x6e, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x0a,
|
||||
0x20, 0x2a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x72, 0x63, 0x2f, 0x57,
|
||||
0x65, 0x62, 0x43, 0x66, 0x67, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x73, 0x74,
|
||||
0x61, 0x6e, 0x74, 0x73, 0x2e, 0x68, 0x20, 0x61, 0x73, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x63,
|
||||
0x73, 0x73, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
|
||||
0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x3a, 0x29, 0x0a, 0x2a, 0x2f, 0x0a, 0x0a, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x61, 0x6e,
|
||||
0x73, 0x3a, 0x20, 0x27, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x27, 0x2c, 0x2d, 0x61, 0x70, 0x70, 0x6c,
|
||||
0x65, 0x2d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x42, 0x6c, 0x69, 0x6e, 0x6b, 0x4d, 0x61,
|
||||
0x63, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x46, 0x6f, 0x6e, 0x74, 0x2c, 0x27, 0x53, 0x65, 0x67,
|
||||
0x6f, 0x65, 0x20, 0x55, 0x49, 0x27, 0x2c, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f, 0x2c, 0x4f, 0x78,
|
||||
0x79, 0x67, 0x65, 0x6e, 0x2c, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x2c, 0x43, 0x61, 0x6e, 0x74,
|
||||
0x61, 0x72, 0x65, 0x6c, 0x6c, 0x2c, 0x27, 0x4f, 0x70, 0x65, 0x6e, 0x20, 0x53, 0x61, 0x6e, 0x73,
|
||||
0x27, 0x2c, 0x27, 0x48, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x20, 0x4e, 0x65, 0x75,
|
||||
0x65, 0x27, 0x2c, 0x73, 0x61, 0x6e, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x69, 0x66, 0x2c, 0x27, 0x41,
|
||||
0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69,
|
||||
0x27, 0x2c, 0x27, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x20, 0x45, 0x6d, 0x6f, 0x6a,
|
||||
0x69, 0x27, 0x2c, 0x27, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x20, 0x53, 0x79, 0x6d,
|
||||
0x62, 0x6f, 0x6c, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x66,
|
||||
0x6f, 0x6e, 0x74, 0x2d, 0x6d, 0x6f, 0x6e, 0x6f, 0x3a, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c,
|
||||
0x61, 0x73, 0x2c, 0x6d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x2c, 0x27, 0x55, 0x62, 0x75, 0x6e, 0x74,
|
||||
0x75, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x27, 0x2c, 0x27, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x27, 0x2c, 0x27, 0x43, 0x6f, 0x75, 0x72, 0x69,
|
||||
0x65, 0x72, 0x20, 0x4e, 0x65, 0x77, 0x27, 0x2c, 0x43, 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c,
|
||||
0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32, 0x3a, 0x20, 0x23,
|
||||
0x31, 0x61, 0x31, 0x61, 0x31, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e,
|
||||
0x63, 0x2d, 0x62, 0x67, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x3a, 0x20, 0x23, 0x66,
|
||||
0x36, 0x66, 0x38, 0x66, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x62, 0x67, 0x2d, 0x33, 0x3a, 0x20, 0x23, 0x65, 0x35, 0x65, 0x37, 0x65, 0x62, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x3a, 0x20,
|
||||
0x23, 0x30, 0x30, 0x37, 0x30, 0x66, 0x33, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x32, 0x3a, 0x20, 0x23, 0x30, 0x33, 0x36, 0x36, 0x64, 0x36,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74,
|
||||
0x78, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x37, 0x39, 0x66, 0x66, 0x65, 0x31,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x74,
|
||||
0x78, 0x3a, 0x20, 0x23, 0x30, 0x63, 0x34, 0x30, 0x34, 0x37, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x28, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x2d,
|
||||
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x3a, 0x20, 0x64, 0x61,
|
||||
0x72, 0x6b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72, 0x6f, 0x6f, 0x74,
|
||||
0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x74, 0x78, 0x2d, 0x31, 0x3a, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32, 0x3a, 0x20,
|
||||
0x23, 0x65, 0x65, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x0d,
|
||||
0x31, 0x61, 0x31, 0x61, 0x31, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x62, 0x67, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x3a, 0x20, 0x23, 0x66, 0x36, 0x66,
|
||||
0x38, 0x66, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67,
|
||||
0x2d, 0x33, 0x3a, 0x20, 0x23, 0x65, 0x35, 0x65, 0x37, 0x65, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x37,
|
||||
0x30, 0x66, 0x33, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b,
|
||||
0x2d, 0x32, 0x3a, 0x20, 0x23, 0x30, 0x33, 0x36, 0x36, 0x64, 0x36, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74, 0x78, 0x3a, 0x20, 0x23, 0x66, 0x66,
|
||||
0x66, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x31,
|
||||
0x3a, 0x20, 0x23, 0x37, 0x39, 0x66, 0x66, 0x65, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x74, 0x78, 0x3a, 0x20, 0x23, 0x30, 0x63, 0x34, 0x30,
|
||||
0x34, 0x37, 0x0a, 0x7d, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x28, 0x70, 0x72, 0x65,
|
||||
0x66, 0x65, 0x72, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||
0x65, 0x3a, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a,
|
||||
0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x3a, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32,
|
||||
0x3a, 0x20, 0x23, 0x65, 0x65, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67,
|
||||
0x2d, 0x32, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x33, 0x3a, 0x20, 0x23, 0x32,
|
||||
0x32, 0x32, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e,
|
||||
0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x33, 0x32, 0x39, 0x31, 0x66, 0x66, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c,
|
||||
0x6b, 0x2d, 0x32, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x37, 0x30, 0x66, 0x33, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74,
|
||||
0x78, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x37, 0x39,
|
||||
0x32, 0x38, 0x63, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x74, 0x78, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2a, 0x20, 0x7b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6d, 0x67, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x70, 0x2c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c,
|
||||
0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x2d, 0x32, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x33, 0x3a, 0x20, 0x23, 0x32, 0x32,
|
||||
0x32, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d,
|
||||
0x6c, 0x6b, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x33, 0x32, 0x39, 0x31, 0x66, 0x66, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x32,
|
||||
0x3a, 0x20, 0x23, 0x30, 0x30, 0x37, 0x30, 0x66, 0x33, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74, 0x78, 0x3a, 0x20, 0x23,
|
||||
0x66, 0x66, 0x66, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e,
|
||||
0x63, 0x2d, 0x61, 0x63, 0x2d, 0x31, 0x3a, 0x20, 0x23, 0x37, 0x39, 0x32, 0x38, 0x63, 0x61, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63,
|
||||
0x2d, 0x74, 0x78, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
|
||||
0x7d, 0x0a, 0x0a, 0x2a, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69,
|
||||
0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x3a, 0x20, 0x30, 0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6d, 0x67, 0x2c, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x70, 0x2c, 0x74, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x75, 0x6c, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
|
||||
0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x75, 0x74,
|
||||
0x74, 0x6f, 0x6e, 0x2c, 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73,
|
||||
0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e,
|
||||
0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x61, 0x6e, 0x73, 0x29, 0x0d, 0x0a, 0x7d,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20,
|
||||
0x37, 0x35, 0x30, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x3a, 0x20, 0x32, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x36,
|
||||
0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f,
|
||||
0x77, 0x2d, 0x78, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3a, 0x20, 0x6e, 0x6f,
|
||||
0x72, 0x6d, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66,
|
||||
0x6c, 0x6f, 0x77, 0x2d, 0x77, 0x72, 0x61, 0x70, 0x3a, 0x20, 0x61, 0x6e, 0x79, 0x77, 0x68, 0x65,
|
||||
0x72, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67,
|
||||
0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
|
||||
0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
|
||||
0x2c, 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61,
|
||||
0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x66,
|
||||
0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x61, 0x6e, 0x73, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x62, 0x6f, 0x64,
|
||||
0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20,
|
||||
0x30, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x37, 0x35, 0x30, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x32, 0x72, 0x65, 0x6d, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69,
|
||||
0x75, 0x73, 0x3a, 0x20, 0x36, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65,
|
||||
0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x78, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3a,
|
||||
0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65,
|
||||
0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x77, 0x72, 0x61, 0x70, 0x3a, 0x20, 0x61, 0x6e, 0x79, 0x77,
|
||||
0x68, 0x65, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62,
|
||||
0x67, 0x2d, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
|
||||
0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x33, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x0d,
|
||||
0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x3a, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63,
|
||||
0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
|
||||
0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x74, 0x78, 0x29,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x31, 0x2c, 0x68, 0x32, 0x2c, 0x68, 0x33, 0x2c,
|
||||
0x68, 0x34, 0x2c, 0x68, 0x35, 0x2c, 0x68, 0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2e, 0x38,
|
||||
0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x31, 0x2c, 0x68,
|
||||
0x32, 0x2c, 0x68, 0x33, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31,
|
||||
0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d,
|
||||
0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
|
||||
0x20, 0x38, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
|
||||
0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f,
|
||||
0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d,
|
||||
0x32, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x34, 0x2c, 0x68, 0x35, 0x2c, 0x68,
|
||||
0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
|
||||
0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x31, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
|
||||
0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x32, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x38, 0x35,
|
||||
0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x33, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31,
|
||||
0x2e, 0x35, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x34, 0x20,
|
||||
0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x68, 0x35, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
|
||||
0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x68, 0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
|
||||
0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x38, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31,
|
||||
0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20,
|
||||
0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
|
||||
0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x32, 0x29, 0x20, 0x21, 0x69, 0x6d,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61,
|
||||
0x62, 0x62, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x62,
|
||||
0x62, 0x72, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x61, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x62, 0x75, 0x74, 0x74,
|
||||
0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75,
|
||||
0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
|
||||
0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79,
|
||||
0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65,
|
||||
0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
|
||||
0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x36, 0x70, 0x78,
|
||||
0x20, 0x31, 0x32, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
|
||||
0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
|
||||
0x77, 0x72, 0x61, 0x70, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d,
|
||||
0x6c, 0x6b, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74,
|
||||
0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a,
|
||||
0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
|
||||
0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x34, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x62, 0x6f,
|
||||
0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
|
||||
0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74, 0x78, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x61, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5b, 0x64, 0x69, 0x73, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
|
||||
0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x64, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65,
|
||||
0x73, 0x65, 0x74, 0x5d, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x69,
|
||||
0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||
0x5d, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75,
|
||||
0x6c, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
|
||||
0x3a, 0x20, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x6e, 0x6f, 0x74, 0x2d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0d, 0x0a,
|
||||
0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x66, 0x6f, 0x63,
|
||||
0x75, 0x73, 0x2c, 0x2e, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72,
|
||||
0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x62, 0x75,
|
||||
0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x66, 0x6f,
|
||||
0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62,
|
||||
0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x66,
|
||||
0x6f, 0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
|
||||
0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x3a,
|
||||
0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
|
||||
0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x32, 0x29,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6c, 0x61,
|
||||
0x70, 0x73, 0x65, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d,
|
||||
0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x64, 0x2c, 0x74, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73,
|
||||
0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67,
|
||||
0x2d, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61,
|
||||
0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x0d,
|
||||
0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x74, 0x72, 0x3a, 0x6e, 0x74, 0x68, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x65, 0x76,
|
||||
0x65, 0x6e, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d,
|
||||
0x62, 0x67, 0x2d, 0x32, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x65, 0x78, 0x74,
|
||||
0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74,
|
||||
0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
|
||||
0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x36, 0x70, 0x78, 0x20, 0x31, 0x32, 0x70, 0x78,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f,
|
||||
0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61,
|
||||
0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20,
|
||||
0x31, 0x2e, 0x30, 0x33, 0x72, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
|
||||
0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x0a, 0x7d, 0x0a,
|
||||
0x0a, 0x3a, 0x3a, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76,
|
||||
0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x31, 0x29, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
|
||||
0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
|
||||
0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x33, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
|
||||
0x69, 0x75, 0x73, 0x3a, 0x20, 0x34, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
|
||||
0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x69, 0x6e, 0x67,
|
||||
0x3a, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x69, 0x6d, 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
|
||||
0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x64, 0x3e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20,
|
||||
0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62,
|
||||
0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74,
|
||||
0x64, 0x3e, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74,
|
||||
0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x64, 0x3e,
|
||||
0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
|
||||
0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
|
||||
0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x72, 0x65, 0x64, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61,
|
||||
0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x28, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x36, 0x30, 0x30,
|
||||
0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64, 0x61, 0x70,
|
||||
0x74, 0x20, 0x74, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64, 0x61,
|
||||
0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74, 0x65,
|
||||
0x78, 0x74, 0x5d, 0x2c, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5d, 0x2c,
|
||||
0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70,
|
||||
0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74,
|
||||
0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74,
|
||||
0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64,
|
||||
0x61, 0x70, 0x74, 0x20, 0x74, 0x64, 0x3a, 0x68, 0x61, 0x73, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x29,
|
||||
0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
|
||||
0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64,
|
||||
0x61, 0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x65, 0x6d,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
|
||||
0x74, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x65, 0x6d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x20, 0x74, 0x64, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69,
|
||||
0x6c, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
|
||||
0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64,
|
||||
0x61, 0x70, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x64, 0x3a, 0x6c, 0x61, 0x73,
|
||||
0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23,
|
||||
0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x3e, 0x73, 0x70, 0x61, 0x6e,
|
||||
0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x34, 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61,
|
||||
0x76, 0x20, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
|
||||
0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
|
||||
0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f,
|
||||
0x6c, 0x69, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
|
||||
0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
|
||||
0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
|
||||
0x3a, 0x20, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
|
||||
0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x36, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
|
||||
0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x6c, 0x69, 0x6e,
|
||||
0x65, 0x61, 0x72, 0x2d, 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x28, 0x74, 0x6f, 0x20,
|
||||
0x6c, 0x65, 0x66, 0x74, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x35, 0x30, 0x25, 0x2c, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x32, 0x35,
|
||||
0x35, 0x2c, 0x32, 0x35, 0x35, 0x2c, 0x30, 0x2e, 0x34, 0x29, 0x20, 0x35, 0x30, 0x25, 0x29, 0x20,
|
||||
0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30,
|
||||
0x25, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x2e, 0x32, 0x73,
|
||||
0x20, 0x65, 0x61, 0x73, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c,
|
||||
0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
|
||||
0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x2d,
|
||||
0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x28, 0x74, 0x6f, 0x20, 0x6c, 0x65, 0x66, 0x74,
|
||||
0x2c, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x20,
|
||||
0x35, 0x30, 0x25, 0x2c, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x32, 0x35, 0x35,
|
||||
0x2c, 0x32, 0x35, 0x35, 0x2c, 0x30, 0x2e, 0x34, 0x29, 0x20, 0x35, 0x30, 0x25, 0x29, 0x20, 0x72,
|
||||
0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x25,
|
||||
0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c,
|
||||
0x6e, 0x61, 0x76, 0x20, 0x61, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61,
|
||||
0x6c, 0x6c, 0x20, 0x2e, 0x34, 0x35, 0x73, 0x20, 0x65, 0x61, 0x73, 0x65, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x3a, 0x61, 0x63, 0x74,
|
||||
0x69, 0x76, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
|
||||
0x6e, 0x63, 0x2d, 0x61, 0x63, 0x2d, 0x74, 0x78, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x31, 0x2c,
|
||||
0x68, 0x32, 0x2c, 0x68, 0x33, 0x2c, 0x68, 0x34, 0x2c, 0x68, 0x35, 0x2c, 0x68, 0x36, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
|
||||
0x3a, 0x20, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x29, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x74, 0x6f, 0x70, 0x3a,
|
||||
0x20, 0x2e, 0x38, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x31, 0x2c, 0x68,
|
||||
0x32, 0x2c, 0x68, 0x33, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31, 0x29,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f,
|
||||
0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d,
|
||||
0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x38, 0x70,
|
||||
0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f,
|
||||
0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20,
|
||||
0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x0a, 0x7d,
|
||||
0x0a, 0x0a, 0x68, 0x34, 0x2c, 0x68, 0x35, 0x2c, 0x68, 0x36, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20,
|
||||
0x2e, 0x33, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x31, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x2e, 0x32,
|
||||
0x35, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x32, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x38, 0x35,
|
||||
0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x33, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x35, 0x72,
|
||||
0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x34, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
|
||||
0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65,
|
||||
0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x68, 0x35, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
|
||||
0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a,
|
||||
0x0a, 0x68, 0x36, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
|
||||
0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x38, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a,
|
||||
0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
|
||||
0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x29, 0x0a, 0x7d, 0x0a,
|
||||
0x0a, 0x61, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
|
||||
0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c,
|
||||
0x6b, 0x2d, 0x32, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b,
|
||||
0x0a, 0x7d, 0x0a, 0x0a, 0x61, 0x62, 0x62, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
|
||||
0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0a, 0x7d, 0x0a, 0x0a, 0x61,
|
||||
0x62, 0x62, 0x72, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0a, 0x7d, 0x0a, 0x0a,
|
||||
0x61, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c,
|
||||
0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f,
|
||||
0x6e, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65,
|
||||
0x73, 0x65, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
|
||||
0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
|
||||
0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69,
|
||||
0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61,
|
||||
0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x36, 0x70, 0x78, 0x20, 0x31, 0x32, 0x70, 0x78, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a,
|
||||
0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
|
||||
0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f,
|
||||
0x6e, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2d, 0x73, 0x70,
|
||||
0x61, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x77, 0x72, 0x61, 0x70, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72,
|
||||
0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x6c, 0x6b, 0x2d, 0x74, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
|
||||
0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
|
||||
0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x34, 0x70, 0x78, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x3a, 0x20,
|
||||
0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x6c, 0x6b, 0x2d, 0x74, 0x78, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x61,
|
||||
0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
||||
0x5d, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x64, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75,
|
||||
0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c,
|
||||
0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74,
|
||||
0x5d, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x5b, 0x64,
|
||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
|
||||
0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x2e, 0x35, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x6e, 0x6f, 0x74,
|
||||
0x2d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x7d, 0x0a, 0x0a, 0x2e, 0x62, 0x75, 0x74,
|
||||
0x74, 0x6f, 0x6e, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x75, 0x74, 0x74, 0x6f,
|
||||
0x6e, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x66,
|
||||
0x6f, 0x63, 0x75, 0x73, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x68, 0x6f, 0x76, 0x65,
|
||||
0x72, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74,
|
||||
0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x68, 0x6f,
|
||||
0x76, 0x65, 0x72, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
|
||||
0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x68, 0x6f,
|
||||
0x76, 0x65, 0x72, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73,
|
||||
0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x3a,
|
||||
0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x6c, 0x6b, 0x2d, 0x32, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
|
||||
0x6c, 0x61, 0x70, 0x73, 0x65, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25,
|
||||
0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x64, 0x2c, 0x74, 0x68, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69,
|
||||
0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x33, 0x29,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e,
|
||||
0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x68,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32,
|
||||
0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x72, 0x3a, 0x6e, 0x74, 0x68, 0x2d, 0x63, 0x68, 0x69, 0x6c,
|
||||
0x64, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
|
||||
0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x78, 0x74,
|
||||
0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77,
|
||||
0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61,
|
||||
0x72, 0x65, 0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x3a, 0x20, 0x36, 0x70, 0x78, 0x20, 0x31, 0x32, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20,
|
||||
0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d,
|
||||
0x6c, 0x6b, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x62, 0x67, 0x2d, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x32, 0x29,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x31, 0x70,
|
||||
0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x62, 0x67, 0x2d, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
|
||||
0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x34, 0x70, 0x78, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20,
|
||||
0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x69,
|
||||
0x7a, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78,
|
||||
0x0a, 0x7d, 0x0a, 0x0a, 0x69, 0x6d, 0x67, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
|
||||
0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0a, 0x7d, 0x0a,
|
||||
0x0a, 0x74, 0x64, 0x3e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
|
||||
0x3a, 0x20, 0x30, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x64, 0x3e, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72,
|
||||
0x65, 0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
|
||||
0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
|
||||
0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0a, 0x7d, 0x0a, 0x0a,
|
||||
0x74, 0x64, 0x3e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
|
||||
0x3a, 0x20, 0x30, 0x0a, 0x7d, 0x0a, 0x0a, 0x2e, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x65, 0x64,
|
||||
0x0a, 0x7d, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20,
|
||||
0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6d, 0x61, 0x78, 0x2d,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x36, 0x30, 0x30, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x64, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79,
|
||||
0x70, 0x65, 0x3d, 0x74, 0x65, 0x78, 0x74, 0x5d, 0x2c, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20,
|
||||
0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x70, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x5d, 0x2c, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x2e,
|
||||
0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x2e,
|
||||
0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30,
|
||||
0x30, 0x25, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61,
|
||||
0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x64, 0x3a, 0x68, 0x61, 0x73, 0x28, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d,
|
||||
0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
|
||||
0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74,
|
||||
0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63,
|
||||
0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e,
|
||||
0x35, 0x65, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e,
|
||||
0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x64, 0x3a, 0x66,
|
||||
0x69, 0x72, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74,
|
||||
0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x64,
|
||||
0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x7b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70,
|
||||
0x3a, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23,
|
||||
0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x3e, 0x73, 0x70, 0x61, 0x6e,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77,
|
||||
0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x34, 0x30, 0x70, 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
|
||||
0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
|
||||
0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d,
|
||||
0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x36, 0x72, 0x65, 0x6d,
|
||||
0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69,
|
||||
0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x74, 0x78, 0x2d, 0x31,
|
||||
0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x6c, 0x69,
|
||||
0x6e, 0x65, 0x61, 0x72, 0x2d, 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x28, 0x74, 0x6f,
|
||||
0x20, 0x6c, 0x65, 0x66, 0x74, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x35, 0x30, 0x25, 0x2c, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x32,
|
||||
0x35, 0x35, 0x2c, 0x32, 0x35, 0x35, 0x2c, 0x30, 0x2e, 0x34, 0x29, 0x20, 0x35, 0x30, 0x25, 0x29,
|
||||
0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30,
|
||||
0x25, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x2e, 0x32, 0x73, 0x20,
|
||||
0x65, 0x61, 0x73, 0x65, 0x0a, 0x7d, 0x0a, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20,
|
||||
0x61, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x3a, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x2d, 0x67, 0x72, 0x61, 0x64, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x28, 0x74, 0x6f, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2c, 0x76, 0x61, 0x72, 0x28,
|
||||
0x2d, 0x2d, 0x6e, 0x63, 0x2d, 0x62, 0x67, 0x2d, 0x32, 0x29, 0x20, 0x35, 0x30, 0x25, 0x2c, 0x72,
|
||||
0x67, 0x62, 0x61, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x32, 0x35, 0x35, 0x2c, 0x32, 0x35, 0x35, 0x2c,
|
||||
0x30, 0x2e, 0x34, 0x29, 0x20, 0x35, 0x30, 0x25, 0x29, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x25, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0a,
|
||||
0x7d, 0x0a, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x3a, 0x68, 0x6f, 0x76,
|
||||
0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6c, 0x65,
|
||||
0x66, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x2e, 0x34, 0x35, 0x73, 0x20, 0x65, 0x61, 0x73,
|
||||
0x65, 0x0a, 0x7d, 0x0a, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x3a, 0x61,
|
||||
0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x63,
|
||||
0x2d, 0x6c, 0x6b, 0x2d, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x2e, 0x31, 0x35, 0x73,
|
||||
0x20, 0x65, 0x61, 0x73, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c,
|
||||
0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
|
||||
0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70,
|
||||
0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31,
|
||||
0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61,
|
||||
0x76, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x3e, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e,
|
||||
0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
|
||||
0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x70, 0x78,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66,
|
||||
0x37, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65,
|
||||
0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x65, 0x61, 0x73, 0x65, 0x0a, 0x7d, 0x0a, 0x0a, 0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76,
|
||||
0x20, 0x61, 0x20, 0x6c, 0x69, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69,
|
||||
0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0a, 0x7d, 0x0a, 0x0a,
|
||||
0x23, 0x74, 0x62, 0x6c, 0x6e, 0x61, 0x76, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x3e, 0x73, 0x70, 0x61,
|
||||
0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x72,
|
||||
0x69, 0x67, 0x68, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61,
|
||||
0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31,
|
||||
0x30, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
|
||||
0x23, 0x66, 0x37, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x69, 0x74, 0x61, 0x6c,
|
||||
0x69, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
|
||||
0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x74,
|
||||
0x64, 0x62, 0x74, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
|
||||
0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c,
|
||||
0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x2e, 0x6e, 0x61, 0x76, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20,
|
||||
0x33, 0x37, 0x35, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
|
||||
0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d,
|
||||
0x69, 0x63, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
|
||||
0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0a, 0x7d, 0x0a, 0x0a, 0x2e, 0x74, 0x64, 0x62, 0x74, 0x6e,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67,
|
||||
0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76,
|
||||
0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6d,
|
||||
0x69, 0x64, 0x64, 0x6c, 0x65, 0x0a, 0x7d, 0x0a, 0x0a, 0x2e, 0x6e, 0x61, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20,
|
||||
0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69,
|
||||
0x64, 0x74, 0x68, 0x3a, 0x20, 0x33, 0x37, 0x35, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0a, 0x7d,
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user