diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2125666 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0b76607 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "cmake.configureOnOpen": false, + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#65c89b", + "activityBar.background": "#65c89b", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#945bc4", + "activityBarBadge.foreground": "#e7e7e7", + "commandCenter.border": "#15202b99", + "sash.hoverBorder": "#65c89b", + "statusBar.background": "#42b883", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#359268", + "statusBarItem.remoteBackground": "#42b883", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#42b883", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#42b88399", + "titleBar.inactiveForeground": "#15202b99" + }, + "peacock.color": "#42b883" +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..1522822 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,28 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp12e] +platform = espressif8266@~3.0.0 +board = esp12e +framework = arduino +lib_deps = + arduino-libraries/ArduinoHttpClient@^0.4.0 + adafruit/Adafruit Unified Sensor@^1.1.4 + crankyoldgit/IRremoteESP8266@^2.7.10 + paulstoffregen/Time@^1.6 + arduino-libraries/Arduino_JSON @ ^0.2.0 + mysensors/MySensors NodeManager @ ^1.8.0 + jchristensen/DS3232RTC @ ^2.0.1 + adafruit/Adafruit NeoPixel @ ^1.12.0 + adafruit/DHT sensor library @ ^1.4.6 + adafruit/Adafruit Unified Sensor @ ^1.1.14 + bblanchon/ArduinoJson@^7.1.0 +monitor_speed = 115200 +upload_port = COM6 diff --git a/Colors.h b/src/Colors.h similarity index 100% rename from Colors.h rename to src/Colors.h diff --git a/Configuration.h b/src/Configuration.h similarity index 92% rename from Configuration.h rename to src/Configuration.h index c2b13f9..ea7bb01 100644 --- a/Configuration.h +++ b/src/Configuration.h @@ -1,12 +1,12 @@ -//***************************************************************************** +//****************************************************************************** // Configuration.h // See README.txt for help -//***************************************************************************** +//****************************************************************************** #ifndef CONFIGURATION_H #define CONFIGURATION_H -//***************************************************************************** +//****************************************************************************** // Software settings //***************************************************************************** @@ -21,9 +21,10 @@ //#define WIFI_BEEPS //#define NONE_TECHNICAL_ZERO -#define AUTO_MODECHANGE_TIME 60 // seconds -#define EVENT_TIME 300 // seconds +#define AUTO_MODECHANGE_TIME 180 // s +#define EVENT_TIME 600 // s #define ALARM_LED_COLOR RED +#define NIGHT_BRIGHTNESS_DELAY 1800 // s //#define ABUSE_CORNER_LED_FOR_ALARM //#define POWERON_SELFTEST @@ -32,8 +33,8 @@ #define SHOW_MODE_WEEKDAY #define SHOW_MODE_DATE #define SHOW_MODE_MOONPHASE -//#define SHOW_MODE_SUNRISE_SUNSET // works only if APIKEY is defined -#define SHOW_MODE_TEST +#define SHOW_MODE_SUNRISE_SUNSET +// #define SHOW_MODE_TEST #define WEATHER // Show weather data @@ -61,9 +62,9 @@ //#define FRONTCOVER_NL //#define FRONTCOVER_BINARY -//***************************************************************************** +//****************************************************************************** // Timezone -//***************************************************************************** +//****************************************************************************** //#define TIMEZONE_IDLW // IDLW International Date Line West UTC-12 //#define TIMEZONE_SST // SST Samoa Standard Time UTC-11 @@ -175,6 +176,7 @@ //#define PIN_WIRE_SCL 05 // D1 SCL //#define PIN_WIRE_SDA 04 // D2 SDA #define PIN_MODE_BUTTON 00 // D3 LOW_Flash +#define PIN_MODE_BUTTON_LED 14 // D5 Button LED #define PIN_LED 02 // D4 ESP8266_LED #define PIN_BUZZER 14 // D5 #define PIN_DHT22 12 // D6 diff --git a/Events.h b/src/Events.h similarity index 100% rename from Events.h rename to src/Events.h diff --git a/LICENSE b/src/LICENSE similarity index 100% rename from LICENSE rename to src/LICENSE diff --git a/Languages.h b/src/Languages.h similarity index 100% rename from Languages.h rename to src/Languages.h diff --git a/LedDriver.cpp b/src/LedDriver.cpp similarity index 81% rename from LedDriver.cpp rename to src/LedDriver.cpp index a18a752..8d29952 100644 --- a/LedDriver.cpp +++ b/src/LedDriver.cpp @@ -1,110 +1,110 @@ -//***************************************************************************** -// LedDriver.cpp -//***************************************************************************** - -#include "LedDriver.h" - -LedDriver::LedDriver() { - strip = new Adafruit_NeoPixel(NUMPIXELS, PIN_LEDS_DATA, NEOPIXEL_TYPE); - strip->begin(); -} - -LedDriver::~LedDriver() { -} - -void LedDriver::clear() { - strip->clear(); -} - -void LedDriver::show() { - strip->show(); -} - -void LedDriver::setPixel(uint8_t x, uint8_t y, uint8_t color, uint8_t brightness) { - setPixel(x + y * 11, color, brightness); -} - -void LedDriver::setPixel(uint8_t num, uint8_t color, uint8_t brightness) { -#ifdef LED_LAYOUT_HORIZONTAL_1 - uint8_t ledMap[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, - 111, 112, 113, 110, 114 - }; -#endif - -#ifdef LED_LAYOUT_VERTICAL_1 - uint8_t ledMap[] = { - 1, 21, 22, 41, 42, 61, 62, 81, 82, 101, 103, - 2, 20, 23, 40, 43, 60, 63, 80, 83, 100, 104, - 3, 19, 24, 39, 44, 59, 64, 79, 84, 99, 105, - 4, 18, 25, 38, 45, 58, 65, 78, 85, 98, 106, - 5, 17, 26, 37, 46, 57, 66, 77, 86, 97, 107, - 6, 16, 27, 36, 47, 56, 67, 76, 87, 96, 108, - 7, 15, 28, 35, 48, 55, 68, 75, 88, 95, 109, - 8, 14, 29, 34, 49, 54, 69, 74, 89, 94, 110, - 9, 13, 30, 33, 50, 53, 70, 73, 90, 93, 111, - 10, 12, 31, 32, 51, 52, 71, 72, 91, 92, 112, - 0, 102, 113, 11, 114 - }; -#endif - -#ifdef LED_LAYOUT_VERTICAL_2 - uint8_t ledMap[] = { - 9, 10, 29, 30, 49, 50, 69, 70, 89, 90, 109, - 8, 11, 28, 31, 48, 51, 68, 71, 88, 91, 108, - 7, 12, 27, 32, 47, 52, 67, 72, 87, 92, 107, - 6, 13, 26, 33, 46, 53, 66, 73, 86, 93, 106, - 5, 14, 25, 34, 45, 54, 65, 74, 85, 94, 105, - 4, 15, 24, 35, 44, 55, 64, 75, 84, 95, 104, - 3, 16, 23, 36, 43, 56, 63, 76, 83, 96, 103, - 2, 17, 22, 37, 42, 57, 62, 77, 82, 97, 102, - 1, 18, 21, 38, 41, 58, 61, 78, 81, 98, 101, - 0, 19, 20, 39, 40, 59, 60, 79, 80, 99, 100, - 112, 110, 114, 113, 111 - }; -#endif - -#ifdef LED_LAYOUT_VERTICAL_3 - uint8_t ledMap[] = { - 9, 10, 29, 30, 49, 50, 69, 70, 89, 90, 109, - 8, 11, 28, 31, 48, 51, 68, 71, 88, 91, 108, - 7, 12, 27, 32, 47, 52, 67, 72, 87, 92, 107, - 6, 13, 26, 33, 46, 53, 66, 73, 86, 93, 106, - 5, 14, 25, 34, 45, 54, 65, 74, 85, 94, 105, - 4, 15, 24, 35, 44, 55, 64, 75, 84, 95, 104, - 3, 16, 23, 36, 43, 56, 63, 76, 83, 96, 103, - 2, 17, 22, 37, 42, 57, 62, 77, 82, 97, 102, - 1, 18, 21, 38, 41, 58, 61, 78, 81, 98, 101, - 0, 19, 20, 39, 40, 59, 60, 79, 80, 99, 100, - 111, 110, 113, 112, 114 - }; -#endif - - uint8_t red = brightness * 0.0039 * defaultColors[color].red; - uint8_t green = brightness * 0.0039 * defaultColors[color].green; - uint8_t blue = brightness * 0.0039 * defaultColors[color].blue; - - -#ifdef NEOPIXEL_RGBW - uint8_t white = 0xFF; - if (red < white) white = red; - if (green < white) white = green; - if (blue < white) white = blue; - strip->setPixelColor(ledMap[num], red - white, green - white, blue - white, white); -#endif - -#ifdef NEOPIXEL_RGB - strip->setPixelColor(ledMap[num], red, green, blue); -#endif - - return; -} +//***************************************************************************** +// LedDriver.cpp +//***************************************************************************** + +#include "LedDriver.h" + +LedDriver::LedDriver() { + strip = new Adafruit_NeoPixel(NUMPIXELS, PIN_LEDS_DATA, NEOPIXEL_TYPE); + strip->begin(); +} + +LedDriver::~LedDriver() { +} + +void LedDriver::clear() { + strip->clear(); +} + +void LedDriver::show() { + strip->show(); +} + +void LedDriver::setPixel(uint8_t x, uint8_t y, uint8_t color, uint8_t brightness) { + setPixel(x + y * 11, color, brightness); +} + +void LedDriver::setPixel(uint8_t num, uint8_t color, uint8_t brightness) { +#ifdef LED_LAYOUT_HORIZONTAL_1 + uint8_t ledMap[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, + 110, 111, 112, 113, 114 + }; +#endif + +#ifdef LED_LAYOUT_VERTICAL_1 + uint8_t ledMap[] = { + 1, 21, 22, 41, 42, 61, 62, 81, 82, 101, 103, + 2, 20, 23, 40, 43, 60, 63, 80, 83, 100, 104, + 3, 19, 24, 39, 44, 59, 64, 79, 84, 99, 105, + 4, 18, 25, 38, 45, 58, 65, 78, 85, 98, 106, + 5, 17, 26, 37, 46, 57, 66, 77, 86, 97, 107, + 6, 16, 27, 36, 47, 56, 67, 76, 87, 96, 108, + 7, 15, 28, 35, 48, 55, 68, 75, 88, 95, 109, + 8, 14, 29, 34, 49, 54, 69, 74, 89, 94, 110, + 9, 13, 30, 33, 50, 53, 70, 73, 90, 93, 111, + 10, 12, 31, 32, 51, 52, 71, 72, 91, 92, 112, + 0, 102, 113, 11, 114 + }; +#endif + +#ifdef LED_LAYOUT_VERTICAL_2 + uint8_t ledMap[] = { + 9, 10, 29, 30, 49, 50, 69, 70, 89, 90, 109, + 8, 11, 28, 31, 48, 51, 68, 71, 88, 91, 108, + 7, 12, 27, 32, 47, 52, 67, 72, 87, 92, 107, + 6, 13, 26, 33, 46, 53, 66, 73, 86, 93, 106, + 5, 14, 25, 34, 45, 54, 65, 74, 85, 94, 105, + 4, 15, 24, 35, 44, 55, 64, 75, 84, 95, 104, + 3, 16, 23, 36, 43, 56, 63, 76, 83, 96, 103, + 2, 17, 22, 37, 42, 57, 62, 77, 82, 97, 102, + 1, 18, 21, 38, 41, 58, 61, 78, 81, 98, 101, + 0, 19, 20, 39, 40, 59, 60, 79, 80, 99, 100, + 112, 110, 114, 113, 111 + }; +#endif + +#ifdef LED_LAYOUT_VERTICAL_3 + uint8_t ledMap[] = { + 9, 10, 29, 30, 49, 50, 69, 70, 89, 90, 109, + 8, 11, 28, 31, 48, 51, 68, 71, 88, 91, 108, + 7, 12, 27, 32, 47, 52, 67, 72, 87, 92, 107, + 6, 13, 26, 33, 46, 53, 66, 73, 86, 93, 106, + 5, 14, 25, 34, 45, 54, 65, 74, 85, 94, 105, + 4, 15, 24, 35, 44, 55, 64, 75, 84, 95, 104, + 3, 16, 23, 36, 43, 56, 63, 76, 83, 96, 103, + 2, 17, 22, 37, 42, 57, 62, 77, 82, 97, 102, + 1, 18, 21, 38, 41, 58, 61, 78, 81, 98, 101, + 0, 19, 20, 39, 40, 59, 60, 79, 80, 99, 100, + 111, 110, 113, 112, 114 + }; +#endif + + uint8_t red = brightness * 0.0039 * defaultColors[color].red; + uint8_t green = brightness * 0.0039 * defaultColors[color].green; + uint8_t blue = brightness * 0.0039 * defaultColors[color].blue; + + +#ifdef NEOPIXEL_RGBW + uint8_t white = 0xFF; + if (red < white) white = red; + if (green < white) white = green; + if (blue < white) white = blue; + strip->setPixelColor(ledMap[num], red - white, green - white, blue - white, white); +#endif + +#ifdef NEOPIXEL_RGB + strip->setPixelColor(ledMap[num], red, green, blue); +#endif + + return; +} diff --git a/LedDriver.h b/src/LedDriver.h similarity index 95% rename from LedDriver.h rename to src/LedDriver.h index b9316f9..2a7617d 100644 --- a/LedDriver.h +++ b/src/LedDriver.h @@ -1,27 +1,27 @@ -//***************************************************************************** -// LedDriver.h -//***************************************************************************** - -#ifndef LEDDRIVER_H -#define LEDDRIVER_H - -#include -#include "Configuration.h" -#include "Colors.h" - -class LedDriver { -public: - LedDriver(); - ~LedDriver(); - - void clear(); - void show(); - void setPixel(uint8_t x, uint8_t y, uint8_t color, uint8_t brightness); - void setPixel(uint8_t num, uint8_t color, uint8_t brightness); - -private: - Adafruit_NeoPixel* strip; - -}; - -#endif +//***************************************************************************** +// LedDriver.h +//***************************************************************************** + +#ifndef LEDDRIVER_H +#define LEDDRIVER_H + +#include +#include "Configuration.h" +#include "Colors.h" + +class LedDriver { +public: + LedDriver(); + ~LedDriver(); + + void clear(); + void show(); + void setPixel(uint8_t x, uint8_t y, uint8_t color, uint8_t brightness); + void setPixel(uint8_t num, uint8_t color, uint8_t brightness); + +private: + Adafruit_NeoPixel* strip; + +}; + +#endif diff --git a/Letters.h b/src/Letters.h similarity index 98% rename from Letters.h rename to src/Letters.h index 4d988b1..e69b051 100644 --- a/Letters.h +++ b/src/Letters.h @@ -197,7 +197,8 @@ const char lettersBig[][7] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04 }, // ASCII-Code 0x21 => ! (33) { 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00 }, // ASCII-Code 0x22 => " (34) { 0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a }, // ASCII-Code 0x23 => # (35) - { 0x04, 0x0f, 0x14, 0x0e, 0x05, 0x1e, 0x04 }, // ASCII-Code 0x24 => $ (36) + //{ 0x04, 0x0f, 0x14, 0x0e, 0x05, 0x1e, 0x04 }, // ASCII-Code 0x24 => $ (36) + { 0x36, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00 }, // heart { 0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03 }, // ASCII-Code 0x25 => % (37) { 0x0c, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0d }, // ASCII-Code 0x26 => & (38) { 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00 }, // ASCII-Code 0x27 => ' (39) diff --git a/src/MeteoWeather.cpp b/src/MeteoWeather.cpp new file mode 100644 index 0000000..d308b48 --- /dev/null +++ b/src/MeteoWeather.cpp @@ -0,0 +1,92 @@ +//***************************************************************************** +// MeteoWeather.cpp - Get weather data from Open-Meteo +//***************************************************************************** + +#include "MeteoWeather.h" + +MeteoWeather::MeteoWeather() { +} + +MeteoWeather::~MeteoWeather() { +} + +uint8_t MeteoWeather::getOutdoorConditions(String lat, String lon, String timezone) { + String response; + WiFiClient client; + JsonDocument doc; + timezone.replace("/","%2F"); + if (client.connect("api.open-meteo.com", 80)) { + String url = "/v1/forecast?latitude=" + String(lat) + "&longitude=" + String(lon) + "¤t=is_day,temperature_2m,relative_humidity_2m,surface_pressure&daily=sunrise,sunset&timeformat=unixtime&timezone=" + timezone + "&forecast_days=1"; + client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: api.open-meteo.com" + "\r\n" + "Connection: close\r\n\r\n"); + unsigned long startMillis = millis(); + while (client.available() == 0) { + if (millis() - startMillis > 5000) { + client.stop(); + return 0; + } + } + + while (client.available()) + response = client.readString(); + #ifdef DEBUG + Serial.println("Weather api response:"); + Serial.println(response); + #endif + + response.trim(); + int first = response.indexOf("{"); // Extract json file content of message. + String extract = response.substring(first); + + // Created with https://arduinojson.org/v7/assistant/ + + DeserializationError error = deserializeJson(doc, extract); + + if (error) { + Serial.print("deserializeJson() failed: "); + Serial.println(error.c_str()); + return 0; + } + + float latitude = doc["latitude"]; // 52.52 + double longitude = doc["longitude"]; // 13.419998 + double generationtime_ms = doc["generationtime_ms"]; // 0.054001808166503906 + int utc_offset_seconds = doc["utc_offset_seconds"]; // 7200 + const char* timezone = doc["timezone"]; // "Europe/Berlin" + const char* timezone_abbreviation = doc["timezone_abbreviation"]; // "CEST" + int elevation = doc["elevation"]; // 38 + + JsonObject current_units = doc["current_units"]; + const char* current_units_time = current_units["time"]; // "unixtime" + const char* current_units_interval = current_units["interval"]; // "seconds" + const char* current_units_temperature_2m = current_units["temperature_2m"]; // "°C" + const char* current_units_relative_humidity_2m = current_units["relative_humidity_2m"]; // "%" + const char* current_units_surface_pressure = current_units["surface_pressure"]; // "hPa" + + JsonObject current = doc["current"]; + long current_time = current["time"]; // 1725390000 + int current_interval = current["interval"]; // 900 + float current_temperature_2m = current["temperature_2m"]; // 27.1 + int current_relative_humidity_2m = current["relative_humidity_2m"]; // 53 + float current_surface_pressure = current["surface_pressure"]; // 1010.1 + bool current_isDay = current["isDay"]; // 0 + + JsonObject daily_units = doc["daily_units"]; + const char* daily_units_time = daily_units["time"]; // "unixtime" + const char* daily_units_sunrise = daily_units["sunrise"]; // "unixtime" + const char* daily_units_sunset = daily_units["sunset"]; // "unixtime" + + JsonObject daily = doc["daily"]; + long daily_time_0 = daily["time"][0]; // 1725314400 + long daily_sunrise_0 = daily["sunrise"][0]; // 1725337296 + long daily_sunset_0 = daily["sunset"][0]; // 1725385761 + + temperature = (double)current_temperature_2m; + humidity = (int)current_relative_humidity_2m; + pressure = (int)current_surface_pressure; + sunrise = (int)daily_sunrise_0; // api also provides sunrise / sunset times. Just use them as well. + sunset = (int)daily_sunset_0; + isDay = (bool)current_isDay; + return 1; + } + return 0; +} diff --git a/src/MeteoWeather.h b/src/MeteoWeather.h new file mode 100644 index 0000000..8046958 --- /dev/null +++ b/src/MeteoWeather.h @@ -0,0 +1,31 @@ +//***************************************************************************** +// MeteoWeather.h - Get weather data and sunrise/sunset times from Open-Meteo +//***************************************************************************** + +#ifndef METEOWEATHER_H +#define METEOWEATHER_H + +// #include +#include +#include + +class MeteoWeather { +public: + MeteoWeather(); + ~MeteoWeather(); + + String description; + double temperature; + uint8_t humidity; + uint16_t pressure; + time_t sunrise; + time_t sunset; + bool isDay; + + uint8_t getOutdoorConditions(String lat, String lon, String timezone); + +private: + +}; + +#endif diff --git a/Modes.h b/src/Modes.h similarity index 95% rename from Modes.h rename to src/Modes.h index ba2f1b6..c05c700 100644 --- a/Modes.h +++ b/src/Modes.h @@ -1,70 +1,70 @@ -//****************************************************************************** -// Modes.h -//****************************************************************************** - -#ifndef MODES_H -#define MODES_H - -typedef enum eMode : uint8_t -{ - MODE_TIME, // 0 -#ifdef SHOW_MODE_AMPM - MODE_AMPM, // 1 -#endif -#ifdef SHOW_MODE_SECONDS - MODE_SECONDS, // 2 if SHOW_MODE_AMPM is set - 1 if not set and so on... -#endif -#ifdef SHOW_MODE_WEEKDAY - MODE_WEEKDAY, // 3 if... -#endif -#ifdef SHOW_MODE_DATE - MODE_DATE, // 4 -#endif -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) - MODE_SUNRISE, // 5 - MODE_SUNSET, // 6 -#endif -#ifdef SHOW_MODE_MOONPHASE - MODE_MOONPHASE, // 7 -#endif -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - MODE_TEMP, // 8 -#endif -#ifdef SENSOR_DHT22 - MODE_HUMIDITY, // 9 -#endif -#ifdef WEATHER - MODE_EXT_TEMP, // 10 - MODE_EXT_HUMIDITY, // 11 -#endif -#ifdef BUZZER - MODE_TIMER, // 12 -#endif -#ifdef SHOW_MODE_TEST - MODE_TEST, // 13 - MODE_RED, // 14 - MODE_GREEN, // 15 - MODE_BLUE, // 16 - MODE_WHITE, // 17 -#endif - MODE_COUNT, // 18 - MODE_BLANK, // 19 - MODE_FEED // 20 -} Mode; - -// Overload the ControlType++ operator. -inline Mode& operator++(Mode& eDOW, int) -{ - const uint8_t i = static_cast(eDOW) + 1; - eDOW = static_cast((i) % MODE_COUNT); - return eDOW; -} - -enum eTransition -{ - TRANSITION_NORMAL, // 0 - TRANSITION_MOVEUP, // 1 - TRANSITION_FADE // 2 -}; - -#endif +//****************************************************************************** +// Modes.h +//****************************************************************************** + +#ifndef MODES_H +#define MODES_H + +typedef enum eMode : uint8_t +{ + MODE_TIME, // 0 +#ifdef SHOW_MODE_AMPM + MODE_AMPM, // 1 +#endif +#ifdef SHOW_MODE_SECONDS + MODE_SECONDS, // 2 if SHOW_MODE_AMPM is set - 1 if not set and so on... +#endif +#ifdef SHOW_MODE_WEEKDAY + MODE_WEEKDAY, // 3 if... +#endif +#ifdef SHOW_MODE_DATE + MODE_DATE, // 4 +#endif +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) + MODE_SUNRISE, // 5 + MODE_SUNSET, // 6 +#endif +#ifdef SHOW_MODE_MOONPHASE + MODE_MOONPHASE, // 7 +#endif +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + MODE_TEMP, // 8 +#endif +#ifdef SENSOR_DHT22 + MODE_HUMIDITY, // 9 +#endif +#ifdef WEATHER + MODE_EXT_TEMP, // 10 + MODE_EXT_HUMIDITY, // 11 +#endif +#ifdef BUZZER + MODE_TIMER, // 12 +#endif +#ifdef SHOW_MODE_TEST + MODE_TEST, // 13 + MODE_RED, // 14 + MODE_GREEN, // 15 + MODE_BLUE, // 16 + MODE_WHITE, // 17 +#endif + MODE_COUNT, // 18 + MODE_BLANK, // 19 + MODE_FEED // 20 +} Mode; + +// Overload the ControlType++ operator. +inline Mode& operator++(Mode& eDOW, int) +{ + const uint8_t i = static_cast(eDOW) + 1; + eDOW = static_cast((i) % MODE_COUNT); + return eDOW; +} + +enum eTransition +{ + TRANSITION_NORMAL, // 0 + TRANSITION_MOVEUP, // 1 + TRANSITION_FADE // 2 +}; + +#endif diff --git a/Ntp.cpp b/src/Ntp.cpp similarity index 100% rename from Ntp.cpp rename to src/Ntp.cpp diff --git a/Ntp.h b/src/Ntp.h similarity index 100% rename from Ntp.h rename to src/Ntp.h diff --git a/Numbers.h b/src/Numbers.h similarity index 100% rename from Numbers.h rename to src/Numbers.h diff --git a/Qlockwork.ino b/src/Qlockwork.ino similarity index 96% rename from Qlockwork.ino rename to src/Qlockwork.ino index eb34db3..ccc01d1 100644 --- a/Qlockwork.ino +++ b/src/Qlockwork.ino @@ -1,2671 +1,2742 @@ -//***************************************************************************** -// QLOCKWORK -// An advanced firmware for a DIY "word-clock" -// -// @mc ESP8266 -// @created 12.03.2017 -// -// This source file is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This source file is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -//***************************************************************************** - -#define FIRMWARE_VERSION 20240908 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Colors.h" -#include "Configuration.h" -#include "Events.h" -#include "LedDriver.h" -#include "Modes.h" -#include "Ntp.h" -#include "MeteoWeather.h" -#include "Renderer.h" -#include "Settings.h" -#include "Syslog.h" -#include "Timezone.h" -#include "Timezones.h" -#include "WiFiManager.h" - -//***************************************************************************** -// Init -//***************************************************************************** - -// Servers -ESP8266WebServer webServer(80); -ESP8266HTTPUpdateServer httpUpdater; - -// DHT22 -#ifdef SENSOR_DHT22 -DHT dht(PIN_DHT22, DHT22); -#endif - -// IR receiver -#ifdef IR_RECEIVER -IRrecv irrecv(PIN_IR_RECEIVER); -decode_results irDecodeResult; -#endif - -// Syslog -#ifdef SYSLOGSERVER_SERVER -WiFiUDP wifiUdp; -Syslog syslog(wifiUdp, SYSLOGSERVER_SERVER, SYSLOGSERVER_PORT, HOSTNAME, "QLOCKWORK", LOG_INFO); -#endif - -// RTC -#ifdef RTC_BACKUP -DS3232RTC RTC; -#endif - -// LED driver -LedDriver ledDriver; - -// Renderer -Renderer renderer; - -// Settings -Settings settings; - -// NTP -Ntp ntp; -char ntpServer[] = NTP_SERVER; -uint8_t errorCounterNTP = 0; - -// Screenbuffer -uint16_t matrix[10] = {}; -uint16_t matrixOld[10] = {}; -bool screenBufferNeedsUpdate = true; - -// Mode -Mode mode = MODE_TIME; -Mode lastMode = mode; -uint32_t modeTimeout = 0; -uint32_t autoModeChangeTimer = AUTO_MODECHANGE_TIME; -bool runTransitionOnce = false; -uint8_t autoMode = 0; - -// Time -uint8_t lastDay = 0; -uint8_t lastMinute = 0; -uint8_t lastHour = 0; -uint8_t lastSecond = 0; -// uint32_t last500Millis = 0; -// uint32_t last50Millis = 0; -time_t upTime = 0; -uint8_t randomHour = 0; -uint8_t randomMinute = 0; -uint8_t randomSecond = 0; -uint8_t moonphase = 0; - -// Feed -String feedText = ""; -uint8_t feedColor = WHITE; -uint8_t feedPosition = 0; - -// MeteoWeather -#ifdef WEATHER -MeteoWeather outdoorWeather; -uint8_t errorCounterOutdoorWeather = 0; -#endif - -// DHT22 -float roomTemperature = 0; -float roomHumidity = 0; -uint8_t errorCounterDHT = 0; - -// Brightness and LDR -uint8_t maxBrightness = map(settings.mySettings.brightness, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); -uint8_t brightness = maxBrightness; -#ifdef LDR -uint16_t ldrValue = 0; -uint16_t lastLdrValue = 0; -uint16_t minLdrValue = 511; // The ESP will crash if minLdrValue and maxLdrValue are equal due to an error in map() -uint16_t maxLdrValue = 512; -uint8_t iTargetBrightness = 0; -unsigned long iBrightnessMillis = 0; -#endif - -// Alarm -#ifdef BUZZER -bool alarmTimerSet = false; -uint8_t alarmTimer = 0; -uint8_t alarmTimerSecond = 0; -uint8_t alarmOn = false; -#endif - -// Events -#ifdef EVENT_TIME - uint32_t showEventTimer = EVENT_TIME; -#endif - -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) -bool sunrise_started = false; -unsigned long sunrise_millis = 0; -bool sunset_started = false; -unsigned long sunset_millis = 0; -time_t sunset_unix = 0; -time_t sunrise_unix = 0; -int save_color_sunrise_sunset = settings.mySettings.color; -#endif - -// Misc -uint8_t testColumn = 0; -int updateInfo = 0; -IPAddress myIP = { 0,0,0,0 }; -uint32_t lastButtonPress = 0; -bool testFlag = false; - -//***************************************************************************** -// Setup() -//***************************************************************************** - -void setup() -{ - // init serial port - Serial.begin(SERIAL_SPEED); - while (!Serial); - delay(1000); - - // And the monkey flips the switch. (Akiva Goldsman) - Serial.println(); - Serial.println("*** QLOCKWORK ***"); - Serial.println("Firmware: " + String(FIRMWARE_VERSION)); - -#ifdef POWERON_SELFTEST - renderer.setAllScreenBuffer(matrix); - Serial.println("Set all LEDs to red."); - writeScreenBuffer(matrix, RED, TEST_BRIGHTNESS); - delay(2500); - Serial.println("Set all LEDs to green."); - writeScreenBuffer(matrix, GREEN, TEST_BRIGHTNESS); - delay(2500); - Serial.println("Set all LEDs to blue."); - writeScreenBuffer(matrix, BLUE, TEST_BRIGHTNESS); - delay(2500); - Serial.println("Set all LEDs to white."); - writeScreenBuffer(matrix, WHITE, TEST_BRIGHTNESS); - delay(2500); -#endif - -#ifdef ESP_LED - Serial.println("Setting up ESP-LED."); - pinMode(PIN_LED, OUTPUT); - digitalWrite(PIN_LED, HIGH); -#endif - -#ifdef MODE_BUTTON - Serial.println("Setting up Mode-Button."); - pinMode(PIN_MODE_BUTTON, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PIN_MODE_BUTTON), buttonModeInterrupt, FALLING); -#endif - -#ifdef ONOFF_BUTTON - Serial.println("Setting up Back-Button."); - pinMode(PIN_ONOFF_BUTTON, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PIN_ONOFF_BUTTON), buttonOnOffInterrupt, FALLING); -#endif - -#ifdef TIME_BUTTON - Serial.println("Setting up Time-Button."); - pinMode(PIN_TIME_BUTTON, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PIN_TIME_BUTTON), buttonTimeInterrupt, FALLING); -#endif - -#ifdef BUZZER - Serial.println("Setting up Buzzer."); - pinMode(PIN_BUZZER, OUTPUT); -#endif - -#ifdef SENSOR_DHT22 - Serial.println("Setting up DHT22."); - dht.begin(); -#endif - -#ifdef LDR - Serial.print("Setting up LDR. ABC: "); - settings.mySettings.useAbc ? Serial.println("enabled") : Serial.println("disabled"); - pinMode(PIN_LDR, INPUT); -#endif - -#ifdef IR_RECEIVER - Serial.println("Setting up IR-Receiver."); - irrecv.enableIRIn(); -#endif - - // Start WiFi and services - renderer.clearScreenBuffer(matrix); - renderer.setSmallText("WI", TEXT_POS_TOP, matrix); - renderer.setSmallText("FI", TEXT_POS_BOTTOM, matrix); - writeScreenBuffer(matrix, WHITE, brightness); - WiFiManager wifiManager; - //wifiManager.resetSettings(); - wifiManager.setTimeout(WIFI_SETUP_TIMEOUT); - wifiManager.autoConnect(HOSTNAME, WIFI_AP_PASS); - WiFi.hostname(HOSTNAME); - WiFi.setAutoReconnect(true); - WiFi.setAutoConnect(true); - if (!WiFi.isConnected()) - { - WiFi.mode(WIFI_AP); - Serial.println("No WLAN connected. Staying in AP mode."); - writeScreenBuffer(matrix, RED, brightness); -#if defined(BUZZER) && defined(WIFI_BEEPS) - digitalWrite(PIN_BUZZER, HIGH); - delay(1500); - digitalWrite(PIN_BUZZER, LOW); -#endif - delay(1000); - myIP = WiFi.softAPIP(); - } - else - { - WiFi.mode(WIFI_STA); - Serial.println("WLAN connected. Switching to STA mode."); - Serial.println("RSSI: " + String(WiFi.RSSI())); - writeScreenBuffer(matrix, GREEN, brightness); -#if defined(BUZZER) && defined(WIFI_BEEPS) - for (uint8_t i = 0; i <= 2; i++) - { -#ifdef DEBUG - Serial.println("Beep!"); -#endif - digitalWrite(PIN_BUZZER, HIGH); - delay(100); - digitalWrite(PIN_BUZZER, LOW); - delay(100); - } -#endif - delay(1000); - myIP = WiFi.localIP(); - - // mDNS is needed to see HOSTNAME in Arduino IDE - Serial.println("Starting mDNS responder."); - MDNS.begin(HOSTNAME); - //MDNS.addService("http", "tcp", 80); - - Serial.println("Starting OTA service."); -#ifdef DEBUG - ArduinoOTA.onStart([]() - { - Serial.println("Start OTA update."); - }); - ArduinoOTA.onError([](ota_error_t error) - { - Serial.println("OTA Error: " + String(error)); - if (error == OTA_AUTH_ERROR) Serial.println("Auth failed."); - else if (error == OTA_BEGIN_ERROR) Serial.println("Begin failed."); - else if (error == OTA_CONNECT_ERROR) Serial.println("Connect failed."); - else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive failed."); - else if (error == OTA_END_ERROR) Serial.println("End failed."); - }); - ArduinoOTA.onEnd([]() - { - Serial.println("End OTA update."); - }); -#endif - ArduinoOTA.setPassword(OTA_PASS); - ArduinoOTA.begin(); - -#ifdef SYSLOGSERVER_SERVER - Serial.println("Starting syslog."); -#ifdef APIKEY - syslog.log(LOG_INFO, ";#;dateTime;roomTemperature;roomHumidity;outdoorTemperature;outdoorHumidity;sunriseTime;sunsetTime;ldrValue;errorCounterNTP;errorCounterDHT;errorCounterOutdoorWeather;freeHeapSize;upTime"); -#else - syslog.log(LOG_INFO, ";#;dateTime;roomTemperature;roomHumidity;ldrValue;errorCounterNTP;errorCounterDHT;freeHeapSize;upTime"); -#endif -#endif - - // Get weather from MeteoWeather -#ifdef WEATHER -#ifdef DEBUG - Serial.println("Getting outdoor weather:"); -#endif - !outdoorWeather.getOutdoorConditions(LATITUDE, LONGITUDE, TIMEZONE) ? errorCounterOutdoorWeather++ : errorCounterOutdoorWeather = 0; -#ifdef DEBUG - Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); - Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); - Serial.println("Sunrise: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise))))); - Serial.println("Sunset: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset))))); -#endif -#endif - } - -#ifdef SHOW_IP - WiFi.isConnected() ? feedText = " IP: " : feedText = " AP-IP: "; - feedText += String(myIP[0]) + "." + String(myIP[1]) + "." + String(myIP[2]) + "." + String(myIP[3]) + " "; - feedPosition = 0; - feedColor = WHITE; - mode = MODE_FEED; -#endif - - Serial.println("Starting webserver."); - setupWebServer(); - - Serial.println("Starting updateserver."); - httpUpdater.setup(&webServer); - - renderer.clearScreenBuffer(matrix); - -#ifdef RTC_BACKUP - RTC.begin(); - setSyncProvider(RTC.get); - Serial.print("RTC Sync."); - if (timeStatus() != timeSet) Serial.print(" FAIL!"); - Serial.println(); -#ifdef DEBUG - time_t tempRtcTime = RTC.get(); - Serial.printf("Time (RTC): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempRtcTime), minute(tempRtcTime), second(tempRtcTime), day(tempRtcTime), month(tempRtcTime), year(tempRtcTime)); -#endif -#endif - - // Get the time! - if (WiFi.isConnected()) - { - // Set ESP (and RTC) time from NTP - time_t tempNtpTime = ntp.getTime(ntpServer); - if (tempNtpTime) - { - errorCounterNTP = 0; - setTime(timeZone.toLocal(tempNtpTime)); -#ifdef DEBUG - Serial.printf("Time (NTP): %02u:%02u:%02u %02u.%02u.%04u (UTC)\r\n", hour(tempNtpTime), minute(tempNtpTime), second(tempNtpTime), day(tempNtpTime), month(tempNtpTime), year(tempNtpTime)); - Serial.printf("Drift (ESP): %d sec.\r\n", tempNtpTime - timeZone.toUTC(now())); -#endif -#ifdef RTC_BACKUP - RTC.set(timeZone.toLocal(tempNtpTime)); -#ifdef DEBUG - Serial.printf("Drift (RTC): %d sec.\r\n", tempNtpTime - timeZone.toUTC(RTC.get())); -#endif -#endif - } - else - { - if (errorCounterNTP < 255) - errorCounterNTP++; -#ifdef DEBUG - Serial.printf("Error (NTP): %u\r\n", errorCounterNTP); -#endif - } - } - else - { - WiFi.reconnect(); - } - - // Define a random time - randomSeed(analogRead(A0)); - randomHour = random(0, 24); - randomMinute = random(5, 56); - randomSecond = random(5, 56); - - // Update room conditions -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - getRoomConditions(); -#endif - - // print some infos -#ifdef DEBUG - Serial.printf("Defined events: %u\r\n", sizeof(events) / sizeof(event_t)); - Serial.printf("Day on: %02u:%02u:00\r\n", hour(settings.mySettings.dayOnTime), minute(settings.mySettings.dayOnTime)); - Serial.printf("Night off: %02u:%02u:00\r\n", hour(settings.mySettings.nightOffTime), minute(settings.mySettings.nightOffTime)); - Serial.printf("Alarm1: %02u:%02u:00 ", hour(settings.mySettings.alarm1Time), minute(settings.mySettings.alarm1Time)); - settings.mySettings.alarm1 ? Serial.print("on ") : Serial.print("off "); - Serial.println(settings.mySettings.alarm1Weekdays, BIN); - Serial.printf("Alarm2: %02u:%02u:00 ", hour(settings.mySettings.alarm2Time), minute(settings.mySettings.alarm2Time)); - settings.mySettings.alarm2 ? Serial.print("on ") : Serial.print("off "); - Serial.println(settings.mySettings.alarm2Weekdays, BIN); - Serial.printf("Random time: %02u:%02u:%02u\r\n", randomHour, randomMinute, randomSecond); - Serial.println("DEBUG is on."); -#else - Serial.println("DEBUG is off."); -#endif - - lastDay = day() - 1; - lastHour = hour(); - lastMinute = minute(); - lastSecond = second(); - -#ifdef FRONTCOVER_BINARY - settings.setTransition(TRANSITION_NORMAL); -#endif -} // setup() - -//***************************************************************************** -// Loop() -//***************************************************************************** - -void loop() -{ - //************************************************************************* - // Run once a day - //************************************************************************* - - if (day() != lastDay) - { - lastDay = day(); - screenBufferNeedsUpdate = true; - -#ifdef SHOW_MODE_MOONPHASE - moonphase = getMoonphase(year(), month(), day()); -#endif - - // Reset URL event 0 - events[0].day = 0; - events[0].month = 0; - -#ifdef DEBUG - Serial.printf("Uptime: %u days, %02u:%02u\r\n", int(upTime / 86400), hour(upTime), minute(upTime)); - Serial.printf("Free RAM: %u bytes\r\n", system_get_free_heap_size()); - Serial.printf("Moonphase: %u\r\n", moonphase); -#endif - - // Change color - if (settings.mySettings.colorChange == COLORCHANGE_DAY) - { - settings.mySettings.color = random(0, COLORCHANGE_COUNT + 1); -#ifdef DEBUG - Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); -#endif - } - } - - //************************************************************************* - // Run once every hour - //************************************************************************* - - if (hour() != lastHour) - { - lastHour = hour(); - screenBufferNeedsUpdate = true; - - // Change color - if (settings.mySettings.colorChange == COLORCHANGE_HOUR) - { - settings.mySettings.color = random(0, COLOR_COUNT + 1); -#ifdef DEBUG - Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); -#endif - } - - // Hourly beep -#ifdef BUZZER - if ((settings.mySettings.hourBeep == true) && (mode == MODE_TIME)) - { - digitalWrite(PIN_BUZZER, HIGH); - delay(25); - digitalWrite(PIN_BUZZER, LOW); -#ifdef DEBUG - Serial.println("Beep!"); -#endif - } -#endif - - //********************************************************************* - // Run once every random hour (once a day) - //********************************************************************* - - if (hour() == randomHour) - { - // Get updateinfo -#ifdef UPDATE_INFOSERVER - if (WiFi.isConnected()) - getUpdateInfo(); -#endif - } - - } - - //************************************************************************* - // Run once every minute - //************************************************************************* - - if (minute() != lastMinute) - { - lastMinute = minute(); - screenBufferNeedsUpdate = true; - -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - // Update room conditions - getRoomConditions(); -#endif - -#ifdef BUZZER - // Switch on buzzer for alarm 1 - if (settings.mySettings.alarm1 && (hour() == hour(settings.mySettings.alarm1Time)) && (minute() == minute(settings.mySettings.alarm1Time)) && bitRead(settings.mySettings.alarm1Weekdays, weekday())) - { - alarmOn = BUZZTIME_ALARM_1; -#ifdef DEBUG - Serial.println("Alarm1 on."); -#endif - } - - // Switch on buzzer for alarm 2 - if (settings.mySettings.alarm2 && (hour() == hour(settings.mySettings.alarm2Time)) && (minute() == minute(settings.mySettings.alarm2Time)) && bitRead(settings.mySettings.alarm2Weekdays, weekday())) - { - alarmOn = BUZZTIME_ALARM_2; -#ifdef DEBUG - Serial.println("Alarm2 on."); -#endif - } -#endif - -#ifdef DEBUG - time_t tempEspTime = now(); - Serial.printf("Time (ESP): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempEspTime), minute(tempEspTime), second(tempEspTime), day(tempEspTime), month(tempEspTime), year(tempEspTime)); -#ifdef RTC_BACKUP - time_t tempRtcTime = RTC.get(); - Serial.printf("Time (RTC): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempRtcTime), minute(tempRtcTime), second(tempRtcTime), day(tempRtcTime), month(tempRtcTime), year(tempRtcTime)); -#endif -#endif - - // Set night- and daymode - if ((hour() == hour(settings.mySettings.nightOffTime)) && (minute() == minute(settings.mySettings.nightOffTime))) - { -#ifdef DEBUG - Serial.println("Night off."); -#endif - setMode(MODE_BLANK); - } - - if ((hour() == hour(settings.mySettings.dayOnTime)) && (minute() == minute(settings.mySettings.dayOnTime))) - { -#ifdef DEBUG - Serial.println("Day on."); -#endif - setMode(lastMode); - - if (!WiFi.isConnected()) - ESP.restart(); - } - - //********************************************************************* - // Run once every random minute (once an hour) or if NTP has an error - //********************************************************************* - - if ((minute() == randomMinute) || ((errorCounterNTP > 0) && (errorCounterNTP < 10))) - { - if (WiFi.isConnected()) - { - // Set ESP (and RTC) time from NTP - time_t tempNtpTime = ntp.getTime(ntpServer); - if (tempNtpTime) - { - errorCounterNTP = 0; - setTime(timeZone.toLocal(tempNtpTime)); -#ifdef DEBUG - Serial.printf("Time (NTP): %02u:%02u:%02u %02u.%02u.%04u (UTC)\r\n", hour(tempNtpTime), minute(tempNtpTime), second(tempNtpTime), day(tempNtpTime), month(tempNtpTime), year(tempNtpTime)); - Serial.printf("Drift (ESP): %d sec.\r\n", tempNtpTime - timeZone.toUTC(now())); -#endif -#ifdef RTC_BACKUP - RTC.set(timeZone.toLocal(tempNtpTime)); -#ifdef DEBUG - Serial.printf("Drift (RTC): %d sec.\r\n", tempNtpTime - timeZone.toUTC(RTC.get())); -#endif -#endif - } - else - { - if (errorCounterNTP < 255) errorCounterNTP++; -#ifdef DEBUG - Serial.printf("Error (NTP): %u\r\n", errorCounterNTP); -#endif - } - } - else - { - WiFi.reconnect(); - } - } - - if (minute() == randomMinute) - { - if (WiFi.isConnected()) - { - // Get weather from MeteoWeather -#ifdef WEATHER -#ifdef DEBUG - Serial.println("Getting outdoor weather for latitude " + String(LATITUDE) + " and longitude " + String(LONGITUDE) + ":"); -#endif - !outdoorWeather.getOutdoorConditions(LATITUDE, LONGITUDE, TIMEZONE) ? errorCounterOutdoorWeather++ : errorCounterOutdoorWeather = 0; -#ifdef DEBUG - Serial.println("Latitude: " + String(LATITUDE)); - Serial.println("Longitude: " + String(LONGITUDE)); - Serial.println("Timezone: " + String(TIMEZONE)); - Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); - Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); - Serial.println("Sunrise: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise))))); - Serial.println("Sunset: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset))))); -#endif -#endif - } - else - { - WiFi.reconnect(); - } - } - - //********************************************************************* - // Run once every 5 minutes - //********************************************************************* - - if (minute() % 5 == 0) - { -#ifdef SYSLOGSERVER_SERVER - // Write some data to syslog - if (WiFi.isConnected()) - { - time_t tempEspTime = now(); -#ifdef WEATHER - syslog.log(LOG_INFO, ";D;" + String(tempEspTime) + ";" + String(roomTemperature) + ";" + String(roomHumidity) + ";" + String(outdoorWeather.temperature) + ";" + String(outdoorWeather.humidity) + ";" \ - + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise)))) + ";" \ - + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset)))) + ";" + String(ldrValue)\ - + ";" + String(errorCounterNTP) + ";" + String(errorCounterDHT) + ";" + String(errorCounterOutdoorWeather) + ";" + String(ESP.getFreeHeap()) + ";" + String(upTime)); -#else - syslog.log(LOG_INFO, ";D;" + String(tempEspTime) + ";" + String(roomTemperature) + ";" + String(roomHumidity) + ";" + String(ldrValue)\ - + ";" + String(errorCounterNTP) + ";" + String(errorCounterDHT) + ";" + String(ESP.getFreeHeap()) + ";" + String(upTime)); -#endif -#ifdef DEBUG - Serial.println("Data written to syslog."); -#endif - } -#endif - // Change color - if (settings.mySettings.colorChange == COLORCHANGE_FIVE) - { - settings.mySettings.color = random(0, COLOR_COUNT + 1); -#ifdef DEBUG - Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); -#endif - } - } - } - - //************************************************************************* - // Run once every second - //************************************************************************* - - if (second() != lastSecond) - { - lastSecond = second(); - upTime++; - -#ifdef BUZZER - // Make some noise - if (alarmOn) - { - alarmOn--; - digitalRead(PIN_BUZZER) ? digitalWrite(PIN_BUZZER, LOW) : digitalWrite(PIN_BUZZER, HIGH); - if (!alarmOn) - { -#ifdef DEBUG - Serial.println("Alarm: off"); -#endif - digitalWrite(PIN_BUZZER, LOW); - screenBufferNeedsUpdate = true; - } - } -#endif - -#ifdef FRONTCOVER_BINARY - if (mode != MODE_BLANK) - screenBufferNeedsUpdate = true; -#else - // General Screenbuffer-Update every second. - // (not in MODE_TIME or MODE_BLANK because it will lock the ESP due to TRANSITION_FADE) - if ((mode != MODE_TIME) && (mode != MODE_BLANK)) - screenBufferNeedsUpdate = true; -#endif - - // Flash ESP LED -#ifdef ESP_LED - digitalWrite(PIN_LED, !digitalRead(PIN_LED)); -#endif - - // Countdown timeralarm by one minute in the second it was activated -#ifdef BUZZER - if (alarmTimer && alarmTimerSet && (alarmTimerSecond == second())) - { - alarmTimer--; -#ifdef DEBUG - if (alarmTimer) - Serial.printf("Timeralarm in %u min.\r\n", alarmTimer); -#endif - } - // Switch on buzzer for timer - if (!alarmTimer && alarmTimerSet) - { - alarmTimerSet = false; - alarmOn = BUZZTIME_TIMER; -#ifdef DEBUG - Serial.println("Timeralarm: on"); -#endif - } -#endif - - // Auto switch modes - if (settings.mySettings.modeChange && (mode == MODE_TIME)) - { - autoModeChangeTimer--; - if (!autoModeChangeTimer) - { -#ifdef DEBUG - Serial.println("Auto modechange. (" + String(autoMode) + ")"); -#endif - autoModeChangeTimer = AUTO_MODECHANGE_TIME; - switch (autoMode) - { - case 0: -#ifdef WEATHER - if (WiFi.isConnected()) - { - setMode(MODE_EXT_TEMP); - } - else - { - WiFi.reconnect(); - setMode(MODE_EXT_TEMP); - } -#endif - autoMode = 1; - break; - case 1: -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - setMode(MODE_TEMP); -#else -#ifdef WEATHER - if (WiFi.isConnected()) - { - setMode(MODE_EXT_TEMP); - } - else - { - WiFi.reconnect(); - setMode(MODE_EXT_TEMP); - } -#endif -#endif - autoMode = 0; - break; - } - } - } - - // Show event in feed -#ifdef EVENT_TIME - if (mode == MODE_TIME) - { - showEventTimer--; - if (!showEventTimer) - { - showEventTimer = EVENT_TIME; - for (uint8_t i = 0; i < (sizeof(events) / sizeof(event_t)); i++) - { - if ((day() == events[i].day) && (month() == events[i].month)) - { - if (events[i].year) - feedText = " " + events[i].text + " (" + String(year() - events[i].year) + ") "; - else - feedText = " " + events[i].text + " "; - feedPosition = 0; - feedColor = events[i].color; -#ifdef DEBUG - Serial.println("Event: \"" + feedText + "\""); -#endif - setMode(MODE_FEED); - } - } - } - } -#endif - } - - //************************************************************************* - // Run always - //************************************************************************* - - if (mode == MODE_FEED) - screenBufferNeedsUpdate = true; - - // Call HTTP- and OTA-handle - webServer.handleClient(); - ArduinoOTA.handle(); - - // Set brightness from LDR and update display (not screenbuffer) at 40Hz. -#ifdef LDR - if (settings.mySettings.useAbc) - { - if ((millis() > iBrightnessMillis + 25) && !testFlag) - { - iBrightnessMillis = millis(); - iTargetBrightness = getBrightnessFromLDR(); - if (brightness < iTargetBrightness) brightness++; - if (brightness > iTargetBrightness) brightness--; - writeScreenBuffer(matrix, settings.mySettings.color, brightness); - } - } -#endif - -#ifdef IR_RECEIVER - // Look for IR commands - if (irrecv.decode(&irDecodeResult)) - { -#ifdef DEBUG_IR - Serial.print("IR signal: 0x"); - serialPrintUint64(irDecodeResult.value, HEX); - Serial.println(); -#endif - switch (irDecodeResult.value) - { - case IR_CODE_ONOFF: - buttonOnOffPressed(); - break; - case IR_CODE_TIME: - buttonTimePressed(); - break; - case IR_CODE_MODE: - buttonModePressed(); - break; - } - irrecv.resume(); - } -#endif - - // Render a new screenbuffer if needed - if (screenBufferNeedsUpdate) - { - screenBufferNeedsUpdate = false; - - // Save old screenbuffer (or not if it's the test pattern) - if (testFlag) - { - for (uint8_t i = 0; i <= 9; i++) matrixOld[i] = 0; - testFlag = false; - } - else - for (uint8_t i = 0; i <= 9; i++) matrixOld[i] = matrix[i]; - - switch (mode) - { - case MODE_TIME: -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) - sunrise_started = false; - sunset_started = false; -#endif - renderer.clearScreenBuffer(matrix); - -#ifdef FRONTCOVER_BINARY - matrix[0] = 0b1111000000000000; - matrix[1] = hour() << 5; - matrix[2] = minute() << 5; - matrix[3] = second() << 5; - matrix[5] = 0b1111000000000000; - matrix[6] = day() << 5; - matrix[7] = month() << 5; - matrix[8] = year() - 2000 << 5; -#else - renderer.setTime(hour(), minute(), matrix); - renderer.setCorners(minute(), matrix); - if (!settings.mySettings.itIs && ((minute() / 5) % 6)) renderer.clearEntryWords(matrix); -#endif -#ifdef BUZZER - if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) renderer.setAlarmLed(matrix); -#endif - break; -#ifdef SHOW_MODE_AMPM - case MODE_AMPM: - renderer.clearScreenBuffer(matrix); - isAM() ? renderer.setSmallText("AM", TEXT_POS_MIDDLE, matrix) : renderer.setSmallText("PM", TEXT_POS_MIDDLE, matrix); - break; -#endif -#ifdef SHOW_MODE_SECONDS - case MODE_SECONDS: - renderer.clearScreenBuffer(matrix); - renderer.setCorners(minute(), matrix); - for (uint8_t i = 0; i <= 6; i++) - { - matrix[1 + i] |= numbersBig[second() / 10][i] << 11; - matrix[1 + i] |= numbersBig[second() % 10][i] << 5; - } - break; -#endif -#ifdef SHOW_MODE_WEEKDAY - case MODE_WEEKDAY: - renderer.clearScreenBuffer(matrix); - renderer.setSmallText(String(sWeekday[weekday()][0]) + String(sWeekday[weekday()][1]), TEXT_POS_MIDDLE, matrix); - break; -#endif -#ifdef SHOW_MODE_DATE - case MODE_DATE: - renderer.clearScreenBuffer(matrix); - if (day() < 10) - renderer.setSmallText(("0" + String(day())), TEXT_POS_TOP, matrix); - else - renderer.setSmallText(String(day()), TEXT_POS_TOP, matrix); - if (month() < 10) - renderer.setSmallText(("0" + String(month())), TEXT_POS_BOTTOM, matrix); - else - renderer.setSmallText(String(month()), TEXT_POS_BOTTOM, matrix); - renderer.setPixelInScreenBuffer(5, 4, matrix); - renderer.setPixelInScreenBuffer(5, 9, matrix); - break; -#endif -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) - case MODE_SUNRISE: - if (!sunrise_started) - { - sunrise_unix = timeZone.toLocal(outdoorWeather.sunrise); - sunrise_started = true; - sunrise_millis = millis(); - save_color_sunrise_sunset = settings.mySettings.color; - } - // if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.333) - if (millis() < sunrise_millis + 1000) - { - settings.mySettings.color = YELLOW; - renderer.clearScreenBuffer(matrix); - // Sunrise screen - matrix[0] = 0b0000000000000000; - matrix[1] = 0b0000000000000000; - matrix[2] = 0b0000000000000000; - matrix[3] = 0b0000000000000000; - matrix[4] = 0b0000000000000000; - matrix[5] = 0b0000111000000000; - matrix[6] = 0b0011111110000000; - matrix[7] = 0b0111111111000000; - matrix[8] = 0b0111111111000000; - matrix[9] = 0b1111111111100000; - } - // else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.666) - else if (millis() < sunrise_millis + 2000) - { - renderer.clearScreenBuffer(matrix); - // Sunrise screen - matrix[0] = 0b0000000000000000; - matrix[1] = 0b0000000000000000; - matrix[2] = 0b0000111000000000; - matrix[3] = 0b0011111110000000; - matrix[4] = 0b0111111111000000; - matrix[5] = 0b0111111111000000; - matrix[6] = 0b1111111111100000; - matrix[7] = 0b1111111111100000; - matrix[8] = 0b0111111111000000; - matrix[9] = 0b0111111111000000; - } - // else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5) - else if (millis() < sunrise_millis + 3000) - { - renderer.clearScreenBuffer(matrix); - // Sunrise screen - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011111110000000; - matrix[2] = 0b0111111111000000; - matrix[3] = 0b0111111111000000; - matrix[4] = 0b1111111111100000; - matrix[5] = 0b1111111111100000; - matrix[6] = 0b0111111111000000; - matrix[7] = 0b0111111111000000; - matrix[8] = 0b0011111110000000; - matrix[9] = 0b0000111000000000; - } - //else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 1.5) - else if (millis() < sunrise_millis + 4000 + settings.mySettings.timeout * 1000) - { - renderer.clearScreenBuffer(matrix); - renderer.setTime(hour(sunrise_unix), minute(sunrise_unix), matrix); - renderer.setCorners(minute(sunrise_unix), matrix); - renderer.clearEntryWords(matrix); - } - else - { - sunrise_started = false; - settings.mySettings.color = save_color_sunrise_sunset; - setMode(MODE_TIME); - } - break; - - case MODE_SUNSET: - if (!sunset_started) - { - sunset_unix = timeZone.toLocal(outdoorWeather.sunset); - sunset_started = true; - sunset_millis = millis(); - } - - // Matrix is only updatet every second. - // if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.333) - if (millis() < sunset_millis + 1000) - { - settings.mySettings.color = ORANGE; - renderer.clearScreenBuffer(matrix); - // Sunset screen - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011111110000000; - matrix[2] = 0b0111111111000000; - matrix[3] = 0b0111111111000000; - matrix[4] = 0b1111111111100000; - matrix[5] = 0b1111111111100000; - matrix[6] = 0b0111111111000000; - matrix[7] = 0b0111111111000000; - matrix[8] = 0b0011111110000000; - matrix[9] = 0b0000111000000000; - } - // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.666) - else if (millis() < sunset_millis + 2000) - { - renderer.clearScreenBuffer(matrix); - // Sunset screen - matrix[0] = 0b0000000000000000; - matrix[1] = 0b0000000000000000; - matrix[2] = 0b0000111000000000; - matrix[3] = 0b0011111110000000; - matrix[4] = 0b0111111111000000; - matrix[5] = 0b0111111111000000; - matrix[6] = 0b1111111111100000; - matrix[7] = 0b1111111111100000; - matrix[8] = 0b0111111111000000; - matrix[9] = 0b0111111111000000; - } - // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5) - else if (millis() < sunset_millis + 3000) - { - renderer.clearScreenBuffer(matrix); - // Sunset screen - matrix[0] = 0b0000000000000000; - matrix[1] = 0b0000000000000000; - matrix[2] = 0b0000000000000000; - matrix[3] = 0b0000000000000000; - matrix[4] = 0b0000000000000000; - matrix[5] = 0b0000111000000000; - matrix[6] = 0b0011111110000000; - matrix[7] = 0b0111111111000000; - matrix[8] = 0b0111111111000000; - matrix[9] = 0b1111111111100000; - } - // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 1.5) - else if (millis() < sunset_millis + 4000 + settings.mySettings.timeout * 1000) - { - renderer.clearScreenBuffer(matrix); - renderer.setTime(hour(sunset_unix), minute(sunset_unix), matrix); - renderer.setCorners(minute(sunset_unix), matrix); - renderer.clearEntryWords(matrix); - } - else - { - sunset_started = false; - settings.mySettings.color = save_color_sunrise_sunset; - setMode(MODE_TIME); - } - break; -#endif -#ifdef SHOW_MODE_MOONPHASE - case MODE_MOONPHASE: -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) - settings.mySettings.color = save_color_sunrise_sunset; -#endif - renderer.clearScreenBuffer(matrix); - switch (moonphase) - { - case 0: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011000110000000; - matrix[2] = 0b0100000001000000; - matrix[3] = 0b0100000001000000; - matrix[4] = 0b1000000000100000; - matrix[5] = 0b1000000000100000; - matrix[6] = 0b0100000001000000; - matrix[7] = 0b0100000001000000; - matrix[8] = 0b0011000110000000; - matrix[9] = 0b0000111000000000; - break; - case 1: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0000001110000000; - matrix[2] = 0b0000000111000000; - matrix[3] = 0b0000000111000000; - matrix[4] = 0b0000000111100000; - matrix[5] = 0b0000000111100000; - matrix[6] = 0b0000000111000000; - matrix[7] = 0b0000000111000000; - matrix[8] = 0b0000001110000000; - matrix[9] = 0b0000111000000000; - break; - case 2: - matrix[0] = 0b0000011000000000; - matrix[1] = 0b0000011110000000; - matrix[2] = 0b0000011111000000; - matrix[3] = 0b0000011111000000; - matrix[4] = 0b0000011111100000; - matrix[5] = 0b0000011111100000; - matrix[6] = 0b0000011111000000; - matrix[7] = 0b0000011111000000; - matrix[8] = 0b0000011110000000; - matrix[9] = 0b0000011000000000; - break; - case 3: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0001111110000000; - matrix[2] = 0b0001111111000000; - matrix[3] = 0b0001111111000000; - matrix[4] = 0b0001111111100000; - matrix[5] = 0b0001111111100000; - matrix[6] = 0b0001111111000000; - matrix[7] = 0b0001111111000000; - matrix[8] = 0b0001111110000000; - matrix[9] = 0b0000111000000000; - break; - case 4: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011111110000000; - matrix[2] = 0b0111111111000000; - matrix[3] = 0b0111111111000000; - matrix[4] = 0b1111111111100000; - matrix[5] = 0b1111111111100000; - matrix[6] = 0b0111111111000000; - matrix[7] = 0b0111111111000000; - matrix[8] = 0b0011111110000000; - matrix[9] = 0b0000111000000000; - break; - case 5: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011111100000000; - matrix[2] = 0b0111111100000000; - matrix[3] = 0b0111111100000000; - matrix[4] = 0b1111111100000000; - matrix[5] = 0b1111111100000000; - matrix[6] = 0b0111111100000000; - matrix[7] = 0b0111111100000000; - matrix[8] = 0b0011111100000000; - matrix[9] = 0b0000111000000000; - break; - case 6: - matrix[0] = 0b0000110000000000; - matrix[1] = 0b0011110000000000; - matrix[2] = 0b0111110000000000; - matrix[3] = 0b0111110000000000; - matrix[4] = 0b1111110000000000; - matrix[5] = 0b1111110000000000; - matrix[6] = 0b0111110000000000; - matrix[7] = 0b0111110000000000; - matrix[8] = 0b0011110000000000; - matrix[9] = 0b0000110000000000; - break; - case 7: - matrix[0] = 0b0000111000000000; - matrix[1] = 0b0011100000000000; - matrix[2] = 0b0111000000000000; - matrix[3] = 0b0111000000000000; - matrix[4] = 0b1111000000000000; - matrix[5] = 0b1111000000000000; - matrix[6] = 0b0111000000000000; - matrix[7] = 0b0111000000000000; - matrix[8] = 0b0011100000000000; - matrix[9] = 0b0000111000000000; - break; - } - break; -#endif -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - case MODE_TEMP: -#ifdef DEBUG - Serial.println("Room Temperature: " + String(roomTemperature) + " °C"); -#endif - renderer.clearScreenBuffer(matrix); - if (roomTemperature == 0) - { - matrix[0] = 0b0000000001000000; - matrix[1] = 0b0000000010100000; - matrix[2] = 0b0000000010100000; - matrix[3] = 0b0000000011100000; - } - if (roomTemperature > 0) - { - matrix[0] = 0b0000000001000000; - matrix[1] = 0b0100000010100000; - matrix[2] = 0b1110000010100000; - matrix[3] = 0b0100000011100000; - } - if (roomTemperature < 0) - { - matrix[0] = 0b0000000001000000; - matrix[1] = 0b0000000010100000; - matrix[2] = 0b1110000010100000; - matrix[3] = 0b0000000011100000; - } - renderer.setSmallText(String(int(abs(roomTemperature) + 0.5)), TEXT_POS_BOTTOM, matrix); - break; -#ifdef SENSOR_DHT22 - case MODE_HUMIDITY: -#ifdef DEBUG - Serial.println("Room Humidity: " + String(roomHumidity) + " %rH"); -#endif - renderer.clearScreenBuffer(matrix); - renderer.setSmallText(String(int(roomHumidity + 0.5)), TEXT_POS_TOP, matrix); - matrix[6] = 0b0100100001000000; - matrix[7] = 0b0001000010100000; - matrix[8] = 0b0010000010100000; - matrix[9] = 0b0100100011100000; - break; -#endif -#endif -#ifdef WEATHER - case MODE_EXT_TEMP: -#ifdef DEBUG - Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); -#endif - renderer.clearScreenBuffer(matrix); - if (outdoorWeather.temperature > 0) - { - matrix[1] = 0b0100000000000000; - matrix[2] = 0b1110000000000000; - matrix[3] = 0b0100000000000000; - } - if (outdoorWeather.temperature < 0) - matrix[2] = 0b1110000000000000; - renderer.setSmallText(String(int(abs(outdoorWeather.temperature) + 0.5)), TEXT_POS_BOTTOM, matrix); - break; - case MODE_EXT_HUMIDITY: -#ifdef DEBUG - Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); -#endif - renderer.clearScreenBuffer(matrix); - if (outdoorWeather.humidity < 100) - renderer.setSmallText(String(outdoorWeather.humidity), TEXT_POS_TOP, matrix); - else - { - matrix[0] = 0b0010111011100000; - matrix[1] = 0b0110101010100000; - matrix[2] = 0b0010101010100000; - matrix[3] = 0b0010101010100000; - matrix[4] = 0b0010111011100000; - } - matrix[6] = 0b0100100000000000; - matrix[7] = 0b0001000000000000; - matrix[8] = 0b0010000000000000; - matrix[9] = 0b0100100000000000; - break; -#endif -#ifdef BUZZER - case MODE_TIMER: - renderer.clearScreenBuffer(matrix); - renderer.setSmallText("TI", TEXT_POS_TOP, matrix); - renderer.setSmallText(String(alarmTimer), TEXT_POS_BOTTOM, matrix); - break; -#endif -#ifdef SHOW_MODE_TEST - case MODE_TEST: - renderer.clearScreenBuffer(matrix); - if (testColumn == 10) - testColumn = 0; - matrix[testColumn] = 0b1111111111110000; - testColumn++; - break; - case MODE_RED: - case MODE_GREEN: - case MODE_BLUE: - case MODE_WHITE: - renderer.setAllScreenBuffer(matrix); - testFlag = true; - break; -#endif - case MODE_BLANK: - renderer.clearScreenBuffer(matrix); - break; - case MODE_FEED: - for (uint8_t y = 0; y <= 5; y++) - { - renderer.clearScreenBuffer(matrix); - for (uint8_t z = 0; z <= 6; z++) - { - matrix[2 + z] |= (lettersBig[feedText[feedPosition] - 32][z] << (11 + y)) & 0b1111111111100000; - matrix[2 + z] |= (lettersBig[feedText[feedPosition + 1] - 32][z] << (5 + y)) & 0b1111111111100000; - matrix[2 + z] |= (lettersBig[feedText[feedPosition + 2] - 32][z] << (y - 1)) & 0b1111111111100000; - } - writeScreenBuffer(matrix, feedColor, brightness); - delay(120); - } - feedPosition++; - if (feedPosition == feedText.length() - 2) - { - feedPosition = 0; - setMode(MODE_TIME); - } - break; - } - - // turn off LED behind IR-sensor -#ifdef IR_LETTER_OFF - renderer.unsetPixelInScreenBuffer(IR_LETTER_X, IR_LETTER_Y - 1, matrix); -#endif - - //debugScreenBuffer(matrixOld); -#ifdef DEBUG_MATRIX - debugScreenBuffer(matrix); -#endif - - // write screenbuffer to display - switch (mode) - { - case MODE_TIME: - case MODE_BLANK: - if (settings.mySettings.transition == TRANSITION_NORMAL) - writeScreenBuffer(matrix, settings.mySettings.color, brightness); - if (settings.mySettings.transition == TRANSITION_FADE) - writeScreenBufferFade(matrixOld, matrix, settings.mySettings.color, brightness); - if (settings.mySettings.transition == TRANSITION_MOVEUP) - { - if (minute() % 5 == 0) - moveScreenBufferUp(matrixOld, matrix, settings.mySettings.color, brightness); - else - writeScreenBuffer(matrix, settings.mySettings.color, brightness); - } - break; -#ifdef SHOW_MODE_TEST - case MODE_RED: - writeScreenBuffer(matrix, RED, TEST_BRIGHTNESS); - break; - case MODE_GREEN: - writeScreenBuffer(matrix, GREEN, TEST_BRIGHTNESS); - break; - case MODE_BLUE: - writeScreenBuffer(matrix, BLUE, TEST_BRIGHTNESS); - break; - case MODE_WHITE: - writeScreenBuffer(matrix, WHITE, TEST_BRIGHTNESS); - break; -#endif - case MODE_FEED: - writeScreenBuffer(matrix, feedColor, brightness); - break; - default: - if (runTransitionOnce) - { - if (settings.mySettings.transition == TRANSITION_NORMAL) - writeScreenBuffer(matrix, settings.mySettings.color, brightness); - if (settings.mySettings.transition == TRANSITION_FADE) - writeScreenBufferFade(matrixOld, matrix, settings.mySettings.color, brightness); - if (settings.mySettings.transition == TRANSITION_MOVEUP) - moveScreenBufferUp(matrixOld, matrix, settings.mySettings.color, brightness); - // moveScreenBufferUp(matrixOld, matrix, settings.mySettings.color, brightness); - runTransitionOnce = false; - testColumn = 0; - } - else - writeScreenBuffer(matrix, settings.mySettings.color, brightness); - break; - } - } - - // Wait for mode timeout then switch back to time - if ((millis() > (modeTimeout + settings.mySettings.timeout * 1000)) && modeTimeout) - { -// #if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(APIKEY) -// sunrise_started = false; -// sunset_started = false; -// #endif - setMode(MODE_TIME); - } - -#ifdef DEBUG_FPS - debugFps(); -#endif -} // loop() - -//***************************************************************************** -// Transitions -//***************************************************************************** - -void writeScreenBuffer(uint16_t screenBuffer[], uint8_t color, uint8_t brightness) -{ - ledDriver.clear(); - for (uint8_t y = 0; y <= 9; y++) - { - for (uint8_t x = 0; x <= 10; x++) - { - if (bitRead(screenBuffer[y], 15 - x)) - ledDriver.setPixel(x, y, color, brightness); - } - } - - // Corner LEDs - for (uint8_t y = 0; y <= 3; y++) - { - if (bitRead(screenBuffer[y], 4)) - ledDriver.setPixel(110 + y, color, brightness); - } - - // Alarm LED -#ifdef BUZZER - if (bitRead(screenBuffer[4], 4)) - { -#ifdef ALARM_LED_COLOR -#ifdef ABUSE_CORNER_LED_FOR_ALARM - if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) - ledDriver.setPixel(111, ALARM_LED_COLOR, brightness); - else - if (bitRead(screenBuffer[1], 4)) - ledDriver.setPixel(111, color, brightness); -#else - ledDriver.setPixel(114, ALARM_LED_COLOR, brightness); -#endif -#else - ledDriver.setPixel(114, color, brightness); -#endif - } -#endif - - ledDriver.show(); -} // writeScreenBuffer - -void moveScreenBufferUp(uint16_t screenBufferOld[], uint16_t screenBufferNew[], uint8_t color, uint8_t brightness) -{ - for (uint8_t z = 0; z <= 9; z++) - { - for (uint8_t i = 0; i <= 8; i++) - screenBufferOld[i] = screenBufferOld[i + 1]; - screenBufferOld[9] = screenBufferNew[z]; - writeScreenBuffer(screenBufferOld, color, brightness); - webServer.handleClient(); - delay(50); - } -} // moveScreenBufferUp - -void writeScreenBufferFade(uint16_t screenBufferOld[], uint16_t screenBufferNew[], uint8_t color, uint8_t brightness) -{ - ledDriver.clear(); - uint8_t brightnessBuffer[10][12] = {}; - - // Copy old matrix to buffer - for (uint8_t y = 0; y <= 9; y++) - { - for (uint8_t x = 0; x <= 11; x++) - { - if (bitRead(screenBufferOld[y], 15 - x)) - brightnessBuffer[y][x] = brightness; - } - } - - // Fade old to new matrix - for (uint8_t i = 0; i < brightness; i++) - { - for (uint8_t y = 0; y <= 9; y++) - { - for (uint8_t x = 0; x <= 11; x++) - { - ESP.wdtFeed(); - if (!(bitRead(screenBufferOld[y], 15 - x)) && (bitRead(screenBufferNew[y], 15 - x))) - brightnessBuffer[y][x]++; - if ((bitRead(screenBufferOld[y], 15 - x)) && !(bitRead(screenBufferNew[y], 15 - x))) - brightnessBuffer[y][x]--; - ledDriver.setPixel(x, y, color, brightnessBuffer[y][x]); - } - } - - // Corner LEDs - for (uint8_t y = 0; y <= 3; y++) - ledDriver.setPixel(110 + y, color, brightnessBuffer[y][11]); - - // Alarm LED -#ifdef BUZZER -#ifdef ALARM_LED_COLOR -#ifdef ABUSE_CORNER_LED_FOR_ALARM - if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) - ledDriver.setPixel(111, ALARM_LED_COLOR, brightnessBuffer[4][11]); - else - ledDriver.setPixel(111, color, brightnessBuffer[1][11]); -#else - ledDriver.setPixel(114, ALARM_LED_COLOR, brightnessBuffer[4][11]); -#endif -#else - ledDriver.setPixel(114, color, brightnessBuffer[4][11]); -#endif -#endif - webServer.handleClient(); - ledDriver.show(); - } -} // writeScreenBufferFade - -//***************************************************************************** -// "On/off" pressed -//***************************************************************************** - -void buttonOnOffPressed() -{ -#ifdef DEBUG - Serial.println("On/off pressed."); -#endif - mode == MODE_BLANK ? setLedsOn() : setLedsOff(); -} - -//***************************************************************************** -// "Time" pressed -//***************************************************************************** - -void buttonTimePressed() -{ -#ifdef DEBUG - Serial.println("Time pressed."); -#endif - - // Switch off alarm -#ifdef BUZZER - if (alarmOn) - { -#ifdef DEBUG - Serial.println("Alarm: off"); -#endif - digitalWrite(PIN_BUZZER, LOW); - alarmOn = false; - } -#endif -#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) - settings.mySettings.color = save_color_sunrise_sunset; -#endif - modeTimeout = 0; - setMode(MODE_TIME); -} - -//***************************************************************************** -// "Mode" pressed -//***************************************************************************** - -void buttonModePressed() -{ -#ifdef DEBUG - Serial.println("Mode pressed."); -#endif - - // Switch off alarm -#ifdef BUZZER - if (alarmOn) - { -#ifdef DEBUG - Serial.println("Alarm: off"); -#endif - digitalWrite(PIN_BUZZER, LOW); - alarmOn = false; - setMode(MODE_TIME); - return; - } -#endif - setMode(mode++); -} - -//***************************************************************************** -// Set mode -//***************************************************************************** - -void setMode(Mode newMode) -{ - screenBufferNeedsUpdate = true; - runTransitionOnce = true; - lastMode = mode; - mode = newMode; - - // set timeout for selected mode - switch (mode) - { -#ifdef SHOW_MODE_AMPM - case MODE_AMPM: -#endif -#ifdef SHOW_MODE_SECONDS - case MODE_SECONDS: -#endif -#ifdef SHOW_MODE_WEEKDAY - case MODE_WEEKDAY: -#endif -#ifdef SHOW_MODE_DATE - case MODE_DATE: -#endif -// #if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) -// case MODE_SUNRISE: -// case MODE_SUNSET: -// #endif -#ifdef SHOW_MODE_MOONPHASE - case MODE_MOONPHASE: -#endif -#if defined(RTC_BACKUP) && !defined(SENSOR_DHT22) - case MODE_TEMP: -#endif -#ifdef SENSOR_DHT22 - case MODE_TEMP: - case MODE_HUMIDITY: -#endif -#ifdef WEATHER - case MODE_EXT_TEMP: - case MODE_EXT_HUMIDITY: -#endif - modeTimeout = millis(); - break; - default: - modeTimeout = 0; - break; - } -} - -//***************************************************************************** -// Get brightness from LDR -//***************************************************************************** - -#ifdef LDR -uint8_t getBrightnessFromLDR() -{ -#ifdef LDR_IS_INVERSE - ldrValue = 1024 - analogRead(PIN_LDR); -#else - ldrValue = analogRead(PIN_LDR); -#endif - if (ldrValue < minLdrValue) - minLdrValue = ldrValue; - if (ldrValue > maxLdrValue) - maxLdrValue = ldrValue; - if ((ldrValue >= (lastLdrValue + 10)) || (ldrValue <= (lastLdrValue - 10))) // Hysteresis is 10 - { - lastLdrValue = ldrValue; - return (uint8_t)map(ldrValue, minLdrValue, maxLdrValue, MIN_BRIGHTNESS, maxBrightness); - } - return iTargetBrightness; -} -#endif - -//***************************************************************************** -// Get update info from server -//***************************************************************************** - -#ifdef UPDATE_INFOSERVER -void getUpdateInfo() -{ - WiFiClient wifiClient; - HttpClient httpClient = HttpClient(wifiClient, UPDATE_INFOSERVER, 80); - httpClient.get(UPDATE_INFOFILE); - if (httpClient.responseStatusCode() == 200) - { - String response = httpClient.responseBody(); - response.trim(); - JSONVar updateArray = JSON.parse(response); - if (JSON.typeof(updateArray) == "undefined") - { - #ifdef DEBUG - Serial.println("Parsing updateArray failed!"); - #endif - return; - } - updateInfo = (int)updateArray["channel"]["unstable"]["version"]; - } -#ifdef DEBUG - updateInfo > int(FIRMWARE_VERSION) ? Serial.println("Firmwareupdate available! (" + String(updateInfo) + ")") : Serial.println("Firmware is uptodate."); -#endif -} -#endif - -//***************************************************************************** -// Get room conditions -//***************************************************************************** - -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) -void getRoomConditions() -{ -#if defined(RTC_BACKUP) && !defined(SENSOR_DHT22) - roomTemperature = RTC.temperature() / 4.0 + RTC_TEMPERATURE_OFFSET; -#ifdef DEBUG - Serial.println("Temperature (RTC): " + String(roomTemperature) + "° C"); -#endif -#endif -#ifdef SENSOR_DHT22 - float dhtTemperature = dht.readTemperature(); - float dhtHumidity = dht.readHumidity(); - if (!isnan(dhtTemperature) && !isnan(dhtHumidity)) - { - errorCounterDHT = 0; - roomTemperature = dhtTemperature + DHT_TEMPERATURE_OFFSET; - roomHumidity = dhtHumidity + DHT_HUMIDITY_OFFSET; -#ifdef DEBUG - Serial.println("Temperature (DHT): " + String(roomTemperature) + " °C"); - Serial.println("Humidity (DHT): " + String(roomHumidity) + " %rH"); -#endif - } - else - { - if (errorCounterDHT < 255) - errorCounterDHT++; -#ifdef DEBUG - Serial.printf("Error (DHT): %u\r\n", errorCounterDHT); -#endif - } -#endif -} -#endif - -//***************************************************************************** -// Misc -//***************************************************************************** - -#ifdef MODE_BUTTON -ICACHE_RAM_ATTR void buttonModeInterrupt() -{ - if (millis() > lastButtonPress + 250) - { - lastButtonPress = millis(); - buttonModePressed(); - } -} -#endif - -#ifdef ONOFF_BUTTON -ICACHE_RAM_ATTR void buttonOnOffInterrupt() -{ - if (millis() > lastButtonPress + 250) - { - lastButtonPress = millis(); - buttonOnOffPressed(); - } -} -#endif - -#ifdef TIME_BUTTON -ICACHE_RAM_ATTR void buttonTimeInterrupt() -{ - if (millis() > lastButtonPress + 250) - { - lastButtonPress = millis(); - buttonTimePressed(); - } -} -#endif - -// Switch off LEDs -void setLedsOff() -{ -#ifdef DEBUG - Serial.println("LEDs: off"); -#endif - setMode(MODE_BLANK); -} - -// Switch on LEDs -void setLedsOn() -{ -#ifdef DEBUG - Serial.println("LEDs: on"); -#endif - setMode(lastMode); -} - -// Calculate moonphase -#ifdef SHOW_MODE_MOONPHASE -int getMoonphase(int y, int m, int d) -{ - int b; - int c; - int e; - double jd; - if (m < 3) { - y--; - m += 12; - } - ++m; - c = 365.25 * y; - e = 30.6 * m; - jd = c + e + d - 694039.09; // jd is total days elapsed - jd /= 29.53; // divide by the moon cycle (29.53 days) - b = jd; // int(jd) -> b, take integer part of jd - jd -= b; // subtract integer part to leave fractional part of original jd - b = jd * 8 + 0.5; // scale fraction from 0-8 and round by adding 0.5 - b = b & 7; // 0 and 8 are the same so turn 8 into 0 - return b; -} -#endif - -// Write screenbuffer to console -#ifdef DEBUG_MATRIX -void debugScreenBuffer(uint16_t screenBuffer[]) -{ - const char buchstabensalat[][12] = - { - { 'E', 'S', 'K', 'I', 'S', 'T', 'A', 'F', 'U', 'N', 'F', '1' }, - { 'Z', 'E', 'H', 'N', 'Z', 'W', 'A', 'N', 'Z', 'I', 'G', '2' }, - { 'D', 'R', 'E', 'I', 'V', 'I', 'E', 'R', 'T', 'E', 'L', '3' }, - { 'V', 'O', 'R', 'F', 'U', 'N', 'K', 'N', 'A', 'C', 'H', '4' }, - { 'H', 'A', 'L', 'B', 'A', 'E', 'L', 'F', 'U', 'N', 'F', 'A' }, - { 'E', 'I', 'N', 'S', 'X', 'A', 'M', 'Z', 'W', 'E', 'I', ' ' }, - { 'D', 'R', 'E', 'I', 'P', 'M', 'J', 'V', 'I', 'E', 'R', ' ' }, - { 'S', 'E', 'C', 'H', 'S', 'N', 'L', 'A', 'C', 'H', 'T', ' ' }, - { 'S', 'I', 'E', 'B', 'E', 'N', 'Z', 'W', 'O', 'L', 'F', ' ' }, - { 'Z', 'E', 'H', 'N', 'E', 'U', 'N', 'K', 'U', 'H', 'R', ' ' } - }; - //Serial.println("\033[0;0H"); // set cursor to 0, 0 position - Serial.println(" -----------"); - for (uint8_t y = 0; y <= 9; y++) - { - Serial.print('|'); - for (uint8_t x = 0; x <= 10; x++) - Serial.print((bitRead(screenBuffer[y], 15 - x) ? buchstabensalat[y][x] : ' ')); - Serial.print('|'); - Serial.println((bitRead(screenBuffer[y], 4) ? buchstabensalat[y][11] : ' ')); - } - Serial.println(" -----------"); -} -#endif - -// Write FPS to console -#ifdef DEBUG_FPS -void debugFps() -{ - static uint16_t frames; - static uint32_t lastFpsCheck; - frames++; - //if ((millis() % 1000 == 0) && (millis() != lastFpsCheck)) - if (millis() % 1000 == 0) - { - //lastFpsCheck = millis(); - Serial.printf("FPS: %u\r\n", frames); - frames = 0; - } -} -#endif - -//***************************************************************************** -// Webserver -//***************************************************************************** - -void setupWebServer() -{ - webServer.onNotFound(handleNotFound); - webServer.on("/", handleRoot); - webServer.on("/handleButtonOnOff", []() { buttonOnOffPressed(); callRoot(); }); - webServer.on("/handleButtonSettings", handleButtonSettings); - webServer.on("/handleButtonMode", []() { buttonModePressed(); callRoot(); }); - webServer.on("/handleButtonTime", []() { buttonTimePressed(); callRoot(); }); - webServer.on("/commitSettings", handleCommitSettings); - webServer.on("/reset", handleReset); - webServer.on("/setEvent", handleSetEvent); - webServer.on("/showText", handleShowText); - webServer.on("/control", handleControl); - webServer.begin(); -} - -void callRoot() -{ - webServer.send(200, "text/html", ""); -} - -// Page 404 -void handleNotFound() -{ - webServer.send(404, "text/plain", "404 - File Not Found."); -} - -// Page / -void handleRoot() -{ - String message = "" - "" - "" - "" + String(WEBSITE_TITLE) + "" - "" - "" - "" - "" - "" - "" - "

" + String(WEBSITE_TITLE) + "

"; -#ifdef DEDICATION - message += DEDICATION; - message += "

"; -#endif - if (mode == MODE_BLANK) - message += ""; - else - message += ""; - message += "" - "

" - "" - ""; -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - message += "

"; - message += "
" + String(roomTemperature) + "°C / " + String(roomTemperature * 1.8 + 32.0) + "°F"; -#endif -#ifdef SENSOR_DHT22 - message += "
" + String(roomHumidity) + "%rH" - "
"; - if (roomHumidity < 30) - message += ""; - else - message += ""; - if ((roomHumidity >= 30) && (roomHumidity < 40)) - message += " "; - else - message += " "; - if ((roomHumidity >= 40) && (roomHumidity <= 50)) - message += " "; - else - message += " "; - if ((roomHumidity > 50) && (roomHumidity < 60)) - message += " "; - else - message += " "; - if (roomHumidity >= 60) - message += " "; - else - message += " "; - message += ""; -#endif -#ifdef WEATHER - message += "

" - "
" + String(outdoorWeather.temperature) + "°C / " + String(outdoorWeather.temperature * 1.8 + 32.0) + "°F" +\ - "
" + String(outdoorWeather.humidity) + "%rH" +\ - "
" + String(outdoorWeather.pressure) + " hPa / " + String(outdoorWeather.pressure / 33.865) + " inHg" +\ - "
" + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise)))) +\ - " " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset)))); -#endif - message += "" - "

Qlockwork was with by ch570512" - "
Firmware: " + String(FIRMWARE_VERSION); -#ifdef UPDATE_INFOSERVER - if (updateInfo > int(FIRMWARE_VERSION)) - message += "
Firmwareupdate available! (" + String(updateInfo) + ")"; -#endif -#ifdef DEBUG_WEB - time_t tempEspTime = now(); - message += "

Time: " + String(hour(tempEspTime)) + ":"; - if (minute(tempEspTime) < 10) - message += "0"; - message += String(minute(tempEspTime)); - if (timeZone.locIsDST(now())) - message += " (DST)"; - message += " up " + String(int(upTime / 86400)) + " days, " + String(hour(upTime)) + ":"; - if (minute(upTime) < 10) - message += "0"; - message += String(minute(upTime)); - message += "
" + String(dayStr(weekday(tempEspTime))) + ", " + String(monthStr(month(tempEspTime))) + " " + String(day(tempEspTime)) + ". " + String(year(tempEspTime)); - message += "
Moonphase: " + String(moonphase); - message += "
Free RAM: " + String(ESP.getFreeHeap()) + " bytes"; - message += "
RSSI: " + String(WiFi.RSSI()); -#ifdef LDR - message += "
Brightness: " + String(brightness) + " (ABC: "; - settings.mySettings.useAbc ? message += "enabled" : message += "disabled"; - message += ", min: " + String(MIN_BRIGHTNESS) + ", max : " + String(maxBrightness) + ")"; - message += "
LDR: " + String(ldrValue) + " (min: " + String(minLdrValue) + ", max: " + String(maxLdrValue) + ")"; -#endif - message += "
Error (NTP): " + String(errorCounterNTP); -#ifdef SENSOR_DHT22 - message += "
Error (DHT): " + String(errorCounterDHT); -#endif -#ifdef WEATHER - message += "
Error (MeteoWeather): " + String(errorCounterOutdoorWeather); -#endif - message += "
Reset reason: " + ESP.getResetReason(); - message += "
Flags: "; -#ifdef RTC_BACKUP - message += "RTC "; -#else - message += "RTC "; -#endif -#ifdef SENSOR_DHT22 - message += "DHT22 "; -#else - message += "DHT22 "; -#endif -#ifdef LDR - message += "LDR "; -#else - message += "LDR "; -#endif -#ifdef BUZZER - message += "BUZZER "; -#else - message += "BUZZER "; -#endif -#ifdef IR_RECEIVER - message += "IR_RECEIVER "; -#else - message += "IR_RECEIVER "; -#endif -#ifdef ESP_LED - message += "ESP_LED "; -#else - message += "ESP_LED "; -#endif -#if defined(ONOFF_BUTTON) || defined(MODE_BUTTON) || defined(TIME_BUTTON) - message += "BUTTONS "; -#else - message += "BUTTONS "; -#endif -#endif - message += "
"; - webServer.send(200, "text/html", message); -} - -// Page settings -void handleButtonSettings() -{ -#ifdef DEBUG - Serial.println("Settings pressed."); -#endif - String message = "" - "" - "" - "" + String(WEBSITE_TITLE) + " " TXT_SETTINGS "" - "" - "" - "" - "" - "" - "" - "

" + String(WEBSITE_TITLE) + " " TXT_SETTINGS "

" - "
" - ""; - // ------------------------------------------------------------------------ -#ifdef BUZZER - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; -#endif - // ------------------------------------------------------------------------ -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - message += ""; -#endif - // ------------------------------------------------------------------------ -#ifdef LDR - message += ""; -#endif - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ -#ifndef FRONTCOVER_BINARY - message += ""; -#endif - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += ""; - // ------------------------------------------------------------------------ - message += "
" - TXT_ALARM - " 1" - "" - " h

" - "
" - TXT_ALARM - " 2" - "" - " h

" - "
" - TXT_TIMER - "" - " " TXT_MINUTES - "
" - TXT_HOURBEEP - "" - "
" - "Show temperature" - "" - "
" - "ABC" - "" - "
" - "Brightness" - "" - " %" - "
" - "Color" - "" - "" - "
" - "Colorchange" - "" - "
" - "Transition" - "" - "
" - "Timeout" - "" - " sec." - "
" - "Night off" - "" - "" - " h" - "
" - "Day on" - "" - "" - " h" - "
" - "Show \"It is\"" - "" - "
" - "Set date/time" - "" - "" - "
" - "
" - "
"; - webServer.send(200, "text/html", message); -} - -void handleCommitSettings() -{ -#ifdef DEBUG - Serial.println("Commit settings pressed."); -#endif - // ------------------------------------------------------------------------ -#ifdef BUZZER - time_t alarmTimeFromWeb = 0; - webServer.arg("a1") == "0" ? settings.mySettings.alarm1 = false : settings.mySettings.alarm1 = true; - alarmTimeFromWeb = webServer.arg("a1t").substring(0, 2).toInt() * 3600 + webServer.arg("a1t").substring(3, 5).toInt() * 60; - if (settings.mySettings.alarm1Time != alarmTimeFromWeb) - settings.mySettings.alarm1 = true; - settings.mySettings.alarm1Time = alarmTimeFromWeb; - settings.mySettings.alarm1Weekdays = - webServer.arg("a1w1").toInt() + - webServer.arg("a1w2").toInt() + - webServer.arg("a1w3").toInt() + - webServer.arg("a1w4").toInt() + - webServer.arg("a1w5").toInt() + - webServer.arg("a1w6").toInt() + - webServer.arg("a1w7").toInt(); - // ------------------------------------------------------------------------ - webServer.arg("a2") == "0" ? settings.mySettings.alarm2 = false : settings.mySettings.alarm2 = true; - alarmTimeFromWeb = webServer.arg("a2t").substring(0, 2).toInt() * 3600 + webServer.arg("a2t").substring(3, 5).toInt() * 60; - if (settings.mySettings.alarm2Time != alarmTimeFromWeb) - settings.mySettings.alarm2 = true; - settings.mySettings.alarm2Time = alarmTimeFromWeb; - settings.mySettings.alarm2Weekdays = - webServer.arg("a2w1").toInt() + - webServer.arg("a2w2").toInt() + - webServer.arg("a2w3").toInt() + - webServer.arg("a2w4").toInt() + - webServer.arg("a2w5").toInt() + - webServer.arg("a2w6").toInt() + - webServer.arg("a2w7").toInt(); - // ------------------------------------------------------------------------ - webServer.arg("hb") == "0" ? settings.mySettings.hourBeep = false : settings.mySettings.hourBeep = true; - // ------------------------------------------------------------------------ - if (webServer.arg("ti").toInt()) { - alarmTimer = webServer.arg("ti").toInt(); - alarmTimerSecond = second(); - alarmTimerSet = true; - setMode(MODE_TIMER); -#ifdef DEBUG - Serial.println("Timer started."); -#endif - } - else - { - if (alarmTimerSet) - { - alarmTimer = 0; - alarmTimerSecond = 0; - alarmTimerSet = false; - setMode(MODE_TIME); -#ifdef DEBUG - Serial.println("Timer stopped."); -#endif - } - } -#endif - // ------------------------------------------------------------------------ -#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) - webServer.arg("mc") == "0" ? settings.mySettings.modeChange = false : settings.mySettings.modeChange = true; -#endif - // ------------------------------------------------------------------------ -#ifdef LDR - if (webServer.arg("ab") == "0") - { - settings.mySettings.useAbc = false; - brightness = maxBrightness; - } - else - settings.mySettings.useAbc = true; -#endif - // ------------------------------------------------------------------------ - settings.mySettings.brightness = webServer.arg("br").toInt(); - maxBrightness = map(settings.mySettings.brightness, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); - brightness = maxBrightness; - // ------------------------------------------------------------------------ - settings.mySettings.color = webServer.arg("co").toInt(); - // ------------------------------------------------------------------------ - switch (webServer.arg("cc").toInt()) - { - case 0: - settings.mySettings.colorChange = COLORCHANGE_NO; - break; - case 1: - settings.mySettings.colorChange = COLORCHANGE_FIVE; - break; - case 2: - settings.mySettings.colorChange = COLORCHANGE_HOUR; - break; - case 3: - settings.mySettings.colorChange = COLORCHANGE_DAY; - break; - } - // ------------------------------------------------------------------------ - switch (webServer.arg("tr").toInt()) - { - case 0: - settings.mySettings.transition = TRANSITION_NORMAL; - break; - case 1: - settings.mySettings.transition = TRANSITION_MOVEUP; - break; - case 2: - settings.mySettings.transition = TRANSITION_FADE; - break; - } - // ------------------------------------------------------------------------ - settings.mySettings.timeout = webServer.arg("to").toInt(); - // ------------------------------------------------------------------------ - settings.mySettings.nightOffTime = webServer.arg("no").substring(0, 2).toInt() * 3600 + webServer.arg("no").substring(3, 5).toInt() * 60; - // ------------------------------------------------------------------------ - settings.mySettings.dayOnTime = webServer.arg("do").substring(0, 2).toInt() * 3600 + webServer.arg("do").substring(3, 5).toInt() * 60; - // ------------------------------------------------------------------------ - webServer.arg("ii") == "0" ? settings.mySettings.itIs = false : settings.mySettings.itIs = true; - // ------------------------------------------------------------------------ - if (webServer.arg("st").length()) - { - Serial.println(webServer.arg("st")); - setTime(webServer.arg("st").substring(11, 13).toInt(), webServer.arg("st").substring(14, 16).toInt(), 0, webServer.arg("st").substring(8, 10).toInt(), webServer.arg("st").substring(5, 7).toInt(), webServer.arg("st").substring(0, 4).toInt()); -#ifdef RTC_BACKUP - RTC.set(now()); -#endif - } - // ------------------------------------------------------------------------ - settings.saveToEEPROM(); - callRoot(); - screenBufferNeedsUpdate = true; -} - -// Page reset -void handleReset() -{ - webServer.send(200, "text/plain", "OK. I'll be back!"); - ESP.restart(); -} - -// Page setEvent -void handleSetEvent() -{ - events[0].day = webServer.arg("day").toInt(); - events[0].month = webServer.arg("month").toInt(); - events[0].text = webServer.arg("text").substring(0, 40); - events[0].color = (eColor)webServer.arg("color").toInt();; - webServer.send(200, "text/plain", "OK."); - -#ifdef DEBUG - Serial.println("Event set: " + String(events[0].day) + "." + String(events[0].month) + ". " + events[0].text); -#endif -} - -// Page showText -void handleShowText() -{ - uint8_t feedBuzzer = webServer.arg("buzzer").toInt(); - feedColor = webServer.arg("color").toInt(); - feedText = " " + webServer.arg("text").substring(0, 80) + " "; - feedPosition = 0; - webServer.send(200, "text/plain", "OK."); - -#ifdef DEBUG - Serial.println("Show text: " + webServer.arg("text").substring(0, 80)); -#endif - -#ifdef BUZZER - for (uint8_t i = 0; i < feedBuzzer; i++) - { - digitalWrite(PIN_BUZZER, HIGH); - delay(75); - digitalWrite(PIN_BUZZER, LOW); - delay(100); - } -#endif - - setMode(MODE_FEED); -} - -void handleControl() -{ - setMode((Mode)webServer.arg("mode").toInt()); - webServer.send(200, "text/plain", "OK."); -} - -String padStringZeros(String input) -{ - return (input.length() > 1) ? input : "0" + input; +//***************************************************************************** +// QLOCKWORK +// An advanced firmware for a DIY "word-clock" +// +// @mc ESP8266 +// @created 12.03.2017 +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +//***************************************************************************** + +#define FIRMWARE_VERSION 20241105 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Colors.h" +#include "Configuration.h" +#include "Events.h" +#include "LedDriver.h" +#include "Modes.h" +#include "Ntp.h" +#include "MeteoWeather.h" +#include "Renderer.h" +#include "Settings.h" +#include "Syslog.h" +#include "Timezone.h" +#include "Timezones.h" +#include "WiFiManager.h" + +//***************************************************************************** +// Init +//***************************************************************************** + +// Servers +ESP8266WebServer webServer(80); +ESP8266HTTPUpdateServer httpUpdater; + +// DHT22 +#ifdef SENSOR_DHT22 +DHT dht(PIN_DHT22, DHT22); +#endif + +// IR receiver +#ifdef IR_RECEIVER +IRrecv irrecv(PIN_IR_RECEIVER); +decode_results irDecodeResult; +#endif + +// Syslog +#ifdef SYSLOGSERVER_SERVER +WiFiUDP wifiUdp; +Syslog syslog(wifiUdp, SYSLOGSERVER_SERVER, SYSLOGSERVER_PORT, HOSTNAME, "QLOCKWORK", LOG_INFO); +#endif + +// RTC +#ifdef RTC_BACKUP +DS3232RTC RTC; +#endif + +// LED driver +LedDriver ledDriver; + +// Renderer +Renderer renderer; + +// Settings +Settings settings; + +// NTP +Ntp ntp; +char ntpServer[] = NTP_SERVER; +uint8_t errorCounterNTP = 0; + +// Screenbuffer +uint16_t matrix[10] = {}; +uint16_t matrixOld[10] = {}; +bool screenBufferNeedsUpdate = true; + +// Mode +Mode mode = MODE_TIME; +Mode lastMode = mode; +uint32_t modeTimeout = 0; +uint32_t autoModeChangeTimer = AUTO_MODECHANGE_TIME; +bool runTransitionOnce = false; +uint8_t autoMode = 0; + +// Time +uint8_t lastDay = 0; +uint8_t lastMinute = 0; +uint8_t lastHour = 0; +uint8_t lastSecond = 0; +// uint32_t last500Millis = 0; +// uint32_t last50Millis = 0; +time_t upTime = 0; +uint8_t randomHour = 0; +uint8_t randomMinute = 0; +uint8_t randomSecond = 0; +uint8_t moonphase = 0; + +// Feed +String feedText = ""; +uint8_t feedColor = WHITE; +uint8_t feedPosition = 0; + +// MeteoWeather +#ifdef WEATHER +MeteoWeather outdoorWeather; +uint8_t errorCounterOutdoorWeather = 0; +#endif + +// DHT22 +float roomTemperature = 0; +float roomHumidity = 0; +uint8_t errorCounterDHT = 0; + +// Brightness and LDR +uint8_t maxBrightness_during_daytime = map(settings.mySettings.brightness_during_daytime, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); +uint8_t brightness_during_daytime = maxBrightness_during_daytime; +uint8_t brightness = maxBrightness_during_daytime; +#ifdef WEATHER +uint8_t maxBrightness_during_nighttime = map(settings.mySettings.brightness_during_nighttime, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); +uint8_t brightness_during_nighttime = maxBrightness_during_nighttime; +#endif +#ifdef LDR +uint16_t ldrValue = 0; +uint16_t lastLdrValue = 0; +uint16_t minLdrValue = 511; // The ESP will crash if minLdrValue and maxLdrValue are equal due to an error in map() +uint16_t maxLdrValue = 512; +uint8_t iTargetBrightness = 0; +unsigned long iBrightnessMillis = 0; +#endif + +// Alarm +#ifdef BUZZER +bool alarmTimerSet = false; +uint8_t alarmTimer = 0; +uint8_t alarmTimerSecond = 0; +uint8_t alarmOn = false; +#endif + +// Events +#ifdef EVENT_TIME + uint32_t showEventTimer = EVENT_TIME; +#endif + +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) +bool sunrise_started = false; +unsigned long sunrise_millis = 0; +bool sunset_started = false; +unsigned long sunset_millis = 0; +time_t sunset_unix = 0; +time_t sunrise_unix = 0; +int save_color_sunrise_sunset = settings.mySettings.color; +#endif + +// Misc +uint8_t testColumn = 0; +int updateInfo = 0; +IPAddress myIP = { 0,0,0,0 }; +uint32_t lastButtonPress = 0; +bool testFlag = false; + +//***************************************************************************** +// Setup() +//***************************************************************************** + +void setup() +{ + // init serial port + Serial.begin(SERIAL_SPEED); + while (!Serial); + delay(1000); + + // And the monkey flips the switch. (Akiva Goldsman) + Serial.println(); + Serial.println("*** QLOCKWORK ***"); + Serial.println("Firmware: " + String(FIRMWARE_VERSION)); + +#ifdef POWERON_SELFTEST + renderer.setAllScreenBuffer(matrix); + Serial.println("Set all LEDs to red."); + writeScreenBuffer(matrix, RED, TEST_BRIGHTNESS); + delay(1500); + Serial.println("Set all LEDs to green."); + writeScreenBuffer(matrix, GREEN, TEST_BRIGHTNESS); + delay(1500); + Serial.println("Set all LEDs to blue."); + writeScreenBuffer(matrix, BLUE, TEST_BRIGHTNESS); + delay(1500); + Serial.println("Set all LEDs to white."); + writeScreenBuffer(matrix, WHITE, TEST_BRIGHTNESS); + delay(1500); +#endif + +#ifdef ESP_LED + Serial.println("Setting up ESP-LED."); + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, HIGH); +#endif + +#ifdef MODE_BUTTON + Serial.println("Setting up Mode-Button."); + pinMode(PIN_MODE_BUTTON, INPUT_PULLUP); + pinMode(PIN_MODE_BUTTON_LED, OUTPUT); + attachInterrupt(digitalPinToInterrupt(PIN_MODE_BUTTON), buttonModeInterrupt, FALLING); +#endif + +#ifdef ONOFF_BUTTON + Serial.println("Setting up Back-Button."); + pinMode(PIN_ONOFF_BUTTON, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PIN_ONOFF_BUTTON), buttonOnOffInterrupt, FALLING); +#endif + +#ifdef TIME_BUTTON + Serial.println("Setting up Time-Button."); + pinMode(PIN_TIME_BUTTON, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PIN_TIME_BUTTON), buttonTimeInterrupt, FALLING); +#endif + +#ifdef BUZZER + Serial.println("Setting up Buzzer."); + pinMode(PIN_BUZZER, OUTPUT); +#endif + +#ifdef SENSOR_DHT22 + Serial.println("Setting up DHT22."); + dht.begin(); +#endif + +#ifdef LDR + Serial.print("Setting up LDR. ABC: "); + settings.mySettings.useAbc ? Serial.println("enabled") : Serial.println("disabled"); + pinMode(PIN_LDR, INPUT); +#endif + +#ifdef IR_RECEIVER + Serial.println("Setting up IR-Receiver."); + irrecv.enableIRIn(); +#endif + + // Start WiFi and services + renderer.clearScreenBuffer(matrix); + renderer.setSmallText("WI", TEXT_POS_TOP, matrix); + renderer.setSmallText("FI", TEXT_POS_BOTTOM, matrix); + writeScreenBuffer(matrix, WHITE, brightness); + WiFiManager wifiManager; + //wifiManager.resetSettings(); + wifiManager.setTimeout(WIFI_SETUP_TIMEOUT); + wifiManager.autoConnect(HOSTNAME, WIFI_AP_PASS); + WiFi.hostname(HOSTNAME); + WiFi.setAutoReconnect(true); + WiFi.setAutoConnect(true); + if (!WiFi.isConnected()) + { + WiFi.mode(WIFI_AP); + Serial.println("No WLAN connected. Staying in AP mode."); + writeScreenBuffer(matrix, RED, brightness); +#if defined(BUZZER) && defined(WIFI_BEEPS) + digitalWrite(PIN_BUZZER, HIGH); + delay(1500); + digitalWrite(PIN_BUZZER, LOW); +#endif + delay(1000); + myIP = WiFi.softAPIP(); + } + else + { + WiFi.mode(WIFI_STA); + Serial.println("WLAN connected. Switching to STA mode."); + Serial.println("RSSI: " + String(WiFi.RSSI())); + writeScreenBuffer(matrix, GREEN, brightness); +#if defined(BUZZER) && defined(WIFI_BEEPS) + for (uint8_t i = 0; i <= 2; i++) + { +#ifdef DEBUG + Serial.println("Beep!"); +#endif + digitalWrite(PIN_BUZZER, HIGH); + delay(100); + digitalWrite(PIN_BUZZER, LOW); + delay(100); + } +#endif + delay(1000); + myIP = WiFi.localIP(); + + // mDNS is needed to see HOSTNAME in Arduino IDE + Serial.println("Starting mDNS responder."); + MDNS.begin(HOSTNAME); + //MDNS.addService("http", "tcp", 80); + + Serial.println("Starting OTA service."); +#ifdef DEBUG + ArduinoOTA.onStart([]() + { + Serial.println("Start OTA update."); + }); + ArduinoOTA.onError([](ota_error_t error) + { + Serial.println("OTA Error: " + String(error)); + if (error == OTA_AUTH_ERROR) Serial.println("Auth failed."); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin failed."); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect failed."); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive failed."); + else if (error == OTA_END_ERROR) Serial.println("End failed."); + }); + ArduinoOTA.onEnd([]() + { + Serial.println("End OTA update."); + }); +#endif + ArduinoOTA.setPassword(OTA_PASS); + ArduinoOTA.begin(); + +#ifdef SYSLOGSERVER_SERVER + Serial.println("Starting syslog."); +#ifdef WEATHER + syslog.log(LOG_INFO, ";#;dateTime;roomTemperature;roomHumidity;outdoorTemperature;outdoorHumidity;sunriseTime;sunsetTime;ldrValue;errorCounterNTP;errorCounterDHT;errorCounterOutdoorWeather;freeHeapSize;upTime"); +#else + syslog.log(LOG_INFO, ";#;dateTime;roomTemperature;roomHumidity;ldrValue;errorCounterNTP;errorCounterDHT;freeHeapSize;upTime"); +#endif +#endif + + // Get weather from MeteoWeather +#ifdef WEATHER +#ifdef DEBUG + Serial.println("Getting outdoor weather:"); +#endif + !outdoorWeather.getOutdoorConditions(LATITUDE, LONGITUDE, TIMEZONE) ? errorCounterOutdoorWeather++ : errorCounterOutdoorWeather = 0; +#ifdef DEBUG + Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); + Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); + Serial.println("Sunrise: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise))))); + Serial.println("Sunset: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset))))); + Serial.println("isDay: " + String(outdoorWeather.isDay)); +#endif + if (outdoorWeather.isDay) + { + brightness = brightness_during_daytime; + #ifdef DEBUG + Serial.println("Day brightness set."); + #endif + } + else + { + brightness = brightness_during_nighttime; + #ifdef DEBUG + Serial.println("Night brightness set."); + #endif + } +#endif + } + +#ifdef SHOW_IP + WiFi.isConnected() ? feedText = " IP: " : feedText = " AP-IP: "; + feedText += String(myIP[0]) + "." + String(myIP[1]) + "." + String(myIP[2]) + "." + String(myIP[3]) + " "; + feedPosition = 0; + feedColor = WHITE; + mode = MODE_FEED; +#endif + + Serial.println("Starting webserver."); + setupWebServer(); + + Serial.println("Starting updateserver."); + httpUpdater.setup(&webServer); + + renderer.clearScreenBuffer(matrix); + +#ifdef RTC_BACKUP + RTC.begin(); + setSyncProvider(RTC.get); + Serial.print("RTC Sync."); + if (timeStatus() != timeSet) Serial.print(" FAIL!"); + Serial.println(); +#ifdef DEBUG + time_t tempRtcTime = RTC.get(); + Serial.printf("Time (RTC): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempRtcTime), minute(tempRtcTime), second(tempRtcTime), day(tempRtcTime), month(tempRtcTime), year(tempRtcTime)); +#endif +#endif + + // Get the time! + if (WiFi.isConnected()) + { + // Set ESP (and RTC) time from NTP + time_t tempNtpTime = ntp.getTime(ntpServer); + if (tempNtpTime) + { + errorCounterNTP = 0; + setTime(timeZone.toLocal(tempNtpTime)); +#ifdef DEBUG + Serial.printf("Time (NTP): %02u:%02u:%02u %02u.%02u.%04u (UTC)\r\n", hour(tempNtpTime), minute(tempNtpTime), second(tempNtpTime), day(tempNtpTime), month(tempNtpTime), year(tempNtpTime)); + Serial.printf("Drift (ESP): %d sec.\r\n", tempNtpTime - timeZone.toUTC(now())); +#endif +#ifdef RTC_BACKUP + RTC.set(timeZone.toLocal(tempNtpTime)); +#ifdef DEBUG + Serial.printf("Drift (RTC): %d sec.\r\n", tempNtpTime - timeZone.toUTC(RTC.get())); +#endif +#endif + } + else + { + if (errorCounterNTP < 255) + errorCounterNTP++; +#ifdef DEBUG + Serial.printf("Error (NTP): %u\r\n", errorCounterNTP); +#endif + } + } + else + { + WiFi.reconnect(); + } + + // Define a random time + randomSeed(analogRead(A0)); + randomHour = random(0, 24); + randomMinute = random(5, 56); + randomSecond = random(5, 56); + + // Update room conditions +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + getRoomConditions(); +#endif + + // print some infos +#ifdef DEBUG + Serial.printf("Defined events: %u\r\n", sizeof(events) / sizeof(event_t)); + Serial.printf("Day on: %02u:%02u:00\r\n", hour(settings.mySettings.dayOnTime), minute(settings.mySettings.dayOnTime)); + Serial.printf("Night off: %02u:%02u:00\r\n", hour(settings.mySettings.nightOffTime), minute(settings.mySettings.nightOffTime)); + Serial.printf("Alarm1: %02u:%02u:00 ", hour(settings.mySettings.alarm1Time), minute(settings.mySettings.alarm1Time)); + settings.mySettings.alarm1 ? Serial.print("on ") : Serial.print("off "); + Serial.println(settings.mySettings.alarm1Weekdays, BIN); + Serial.printf("Alarm2: %02u:%02u:00 ", hour(settings.mySettings.alarm2Time), minute(settings.mySettings.alarm2Time)); + settings.mySettings.alarm2 ? Serial.print("on ") : Serial.print("off "); + Serial.println(settings.mySettings.alarm2Weekdays, BIN); + Serial.printf("Random time: %02u:%02u:%02u\r\n", randomHour, randomMinute, randomSecond); + Serial.println("DEBUG is on."); +#else + Serial.println("DEBUG is off."); +#endif + + lastDay = day() - 1; + lastHour = hour(); + lastMinute = minute(); + lastSecond = second(); + +#ifdef FRONTCOVER_BINARY + settings.setTransition(TRANSITION_NORMAL); +#endif +} // setup() + +//***************************************************************************** +// Loop() +//***************************************************************************** + +void loop() +{ + //************************************************************************* + // Run once a day + //************************************************************************* + + if (day() != lastDay) + { + lastDay = day(); + screenBufferNeedsUpdate = true; + +#ifdef SHOW_MODE_MOONPHASE + moonphase = getMoonphase(year(), month(), day()); +#endif + + // Reset URL event 0 + events[0].day = 0; + events[0].month = 0; + +#ifdef DEBUG + Serial.printf("Uptime: %u days, %02u:%02u\r\n", int(upTime / 86400), hour(upTime), minute(upTime)); + Serial.printf("Free RAM: %u bytes\r\n", system_get_free_heap_size()); + Serial.printf("Moonphase: %u\r\n", moonphase); +#endif + + // Change color + if (settings.mySettings.colorChange == COLORCHANGE_DAY) + { + settings.mySettings.color = random(0, COLORCHANGE_COUNT + 1); +#ifdef DEBUG + Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); +#endif + } + } + + //************************************************************************* + // Run once every hour + //************************************************************************* + + if (hour() != lastHour) + { + lastHour = hour(); + screenBufferNeedsUpdate = true; + + // Change color + if (settings.mySettings.colorChange == COLORCHANGE_HOUR) + { + settings.mySettings.color = random(0, COLOR_COUNT + 1); +#ifdef DEBUG + Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); +#endif + } + + // Hourly beep +#ifdef BUZZER + if ((settings.mySettings.hourBeep == true) && (mode == MODE_TIME)) + { + digitalWrite(PIN_BUZZER, HIGH); + delay(25); + digitalWrite(PIN_BUZZER, LOW); +#ifdef DEBUG + Serial.println("Beep!"); +#endif + } +#endif + + //********************************************************************* + // Run once every random hour (once a day) + //********************************************************************* + + if (hour() == randomHour) + { + // Get updateinfo +#ifdef UPDATE_INFOSERVER + if (WiFi.isConnected()) + getUpdateInfo(); +#endif + } + + } + + //************************************************************************* + // Run once every minute + //************************************************************************* + + if (minute() != lastMinute) + { + lastMinute = minute(); + screenBufferNeedsUpdate = true; + +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + // Update room conditions + getRoomConditions(); +#endif + +#ifdef BUZZER + // Switch on buzzer for alarm 1 + if (settings.mySettings.alarm1 && (hour() == hour(settings.mySettings.alarm1Time)) && (minute() == minute(settings.mySettings.alarm1Time)) && bitRead(settings.mySettings.alarm1Weekdays, weekday())) + { + alarmOn = BUZZTIME_ALARM_1; +#ifdef DEBUG + Serial.println("Alarm1 on."); +#endif + } + + // Switch on buzzer for alarm 2 + if (settings.mySettings.alarm2 && (hour() == hour(settings.mySettings.alarm2Time)) && (minute() == minute(settings.mySettings.alarm2Time)) && bitRead(settings.mySettings.alarm2Weekdays, weekday())) + { + alarmOn = BUZZTIME_ALARM_2; +#ifdef DEBUG + Serial.println("Alarm2 on."); +#endif + } +#endif + +#ifdef DEBUG + time_t tempEspTime = now(); + Serial.printf("Time (ESP): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempEspTime), minute(tempEspTime), second(tempEspTime), day(tempEspTime), month(tempEspTime), year(tempEspTime)); +#ifdef RTC_BACKUP + time_t tempRtcTime = RTC.get(); + Serial.printf("Time (RTC): %02u:%02u:%02u %02u.%02u.%04u\r\n", hour(tempRtcTime), minute(tempRtcTime), second(tempRtcTime), day(tempRtcTime), month(tempRtcTime), year(tempRtcTime)); +#endif +#endif + + // Set night- and daymode + if ((hour() == hour(settings.mySettings.nightOffTime)) && (minute() == minute(settings.mySettings.nightOffTime))) + { +#ifdef DEBUG + Serial.println("Night off."); +#endif + setMode(MODE_BLANK); + } + +#ifdef WEATHER + // Set night- and day brightness + if ((hour() == hour(timeZone.toLocal(outdoorWeather.sunset + NIGHT_BRIGHTNESS_DELAY))) && (minute() == minute(timeZone.toLocal(outdoorWeather.sunset + NIGHT_BRIGHTNESS_DELAY)))) + { +#ifdef DEBUG + Serial.println("Night brightness set."); +#endif + brightness = brightness_during_nighttime; + } + if ((hour() == hour(timeZone.toLocal(outdoorWeather.sunrise - NIGHT_BRIGHTNESS_DELAY))) && (minute() == minute(timeZone.toLocal(outdoorWeather.sunrise - NIGHT_BRIGHTNESS_DELAY)))) + { +#ifdef DEBUG + Serial.println("Day brightness set."); +#endif + brightness = brightness_during_nighttime; + } +#endif + + if ((hour() == hour(settings.mySettings.dayOnTime)) && (minute() == minute(settings.mySettings.dayOnTime))) + { +#ifdef DEBUG + Serial.println("Day on."); +#endif + setMode(lastMode); + + if (!WiFi.isConnected()) + ESP.restart(); + } + + //********************************************************************* + // Run once every random minute (once an hour) or if NTP has an error + //********************************************************************* + + if ((minute() == randomMinute) || ((errorCounterNTP > 0) && (errorCounterNTP < 10))) + { + if (WiFi.isConnected()) + { + // Set ESP (and RTC) time from NTP + time_t tempNtpTime = ntp.getTime(ntpServer); + if (tempNtpTime) + { + errorCounterNTP = 0; + setTime(timeZone.toLocal(tempNtpTime)); +#ifdef DEBUG + Serial.printf("Time (NTP): %02u:%02u:%02u %02u.%02u.%04u (UTC)\r\n", hour(tempNtpTime), minute(tempNtpTime), second(tempNtpTime), day(tempNtpTime), month(tempNtpTime), year(tempNtpTime)); + Serial.printf("Drift (ESP): %d sec.\r\n", tempNtpTime - timeZone.toUTC(now())); +#endif +#ifdef RTC_BACKUP + RTC.set(timeZone.toLocal(tempNtpTime)); +#ifdef DEBUG + Serial.printf("Drift (RTC): %d sec.\r\n", tempNtpTime - timeZone.toUTC(RTC.get())); +#endif +#endif + } + else + { + if (errorCounterNTP < 255) errorCounterNTP++; +#ifdef DEBUG + Serial.printf("Error (NTP): %u\r\n", errorCounterNTP); +#endif + } + } + else + { + WiFi.reconnect(); + } + } + + if (minute() == randomMinute) + { + if (WiFi.isConnected()) + { + // Get weather from MeteoWeather +#ifdef WEATHER +#ifdef DEBUG + Serial.println("Getting outdoor weather for latitude " + String(LATITUDE) + " and longitude " + String(LONGITUDE) + ":"); +#endif + !outdoorWeather.getOutdoorConditions(LATITUDE, LONGITUDE, TIMEZONE) ? errorCounterOutdoorWeather++ : errorCounterOutdoorWeather = 0; +#ifdef DEBUG + Serial.println("Latitude: " + String(LATITUDE)); + Serial.println("Longitude: " + String(LONGITUDE)); + Serial.println("Timezone: " + String(TIMEZONE)); + Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); + Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); + Serial.println("Sunrise: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise))))); + Serial.println("Sunset: " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset))))); +#endif +#endif + } + else + { + WiFi.reconnect(); + } + } + + //********************************************************************* + // Run once every 5 minutes + //********************************************************************* + + if (minute() % 5 == 0) + { + digitalWrite(PIN_MODE_BUTTON_LED,LOW); +#ifdef SYSLOGSERVER_SERVER + // Write some data to syslog + if (WiFi.isConnected()) + { + time_t tempEspTime = now(); +#ifdef WEATHER + syslog.log(LOG_INFO, ";D;" + String(tempEspTime) + ";" + String(roomTemperature) + ";" + String(roomHumidity) + ";" + String(outdoorWeather.temperature) + ";" + String(outdoorWeather.humidity) + ";" \ + + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise)))) + ";" \ + + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset)))) + ";" + String(ldrValue)\ + + ";" + String(errorCounterNTP) + ";" + String(errorCounterDHT) + ";" + String(errorCounterOutdoorWeather) + ";" + String(ESP.getFreeHeap()) + ";" + String(upTime)); +#else + syslog.log(LOG_INFO, ";D;" + String(tempEspTime) + ";" + String(roomTemperature) + ";" + String(roomHumidity) + ";" + String(ldrValue)\ + + ";" + String(errorCounterNTP) + ";" + String(errorCounterDHT) + ";" + String(ESP.getFreeHeap()) + ";" + String(upTime)); +#endif +#ifdef DEBUG + Serial.println("Data written to syslog."); +#endif + } +#endif + // Change color + if (settings.mySettings.colorChange == COLORCHANGE_FIVE) + { + settings.mySettings.color = random(0, COLOR_COUNT + 1); +#ifdef DEBUG + Serial.printf("Color changed to: %u\r\n", settings.mySettings.color); +#endif + } + } + } + + //************************************************************************* + // Run once every second + //************************************************************************* + + if (second() != lastSecond) + { + lastSecond = second(); + upTime++; + +#ifdef BUZZER + // Make some noise + if (alarmOn) + { + alarmOn--; + digitalRead(PIN_BUZZER) ? digitalWrite(PIN_BUZZER, LOW) : digitalWrite(PIN_BUZZER, HIGH); + if (!alarmOn) + { +#ifdef DEBUG + Serial.println("Alarm: off"); +#endif + digitalWrite(PIN_BUZZER, LOW); + screenBufferNeedsUpdate = true; + } + } +#endif + +#ifdef FRONTCOVER_BINARY + if (mode != MODE_BLANK) + screenBufferNeedsUpdate = true; +#else + // General Screenbuffer-Update every second. + // (not in MODE_TIME or MODE_BLANK because it will lock the ESP due to TRANSITION_FADE) + if ((mode != MODE_TIME) && (mode != MODE_BLANK)) + screenBufferNeedsUpdate = true; +#endif + + // Flash ESP LED +#ifdef ESP_LED + digitalWrite(PIN_LED, !digitalRead(PIN_LED)); +#endif + + // Countdown timeralarm by one minute in the second it was activated +#ifdef BUZZER + if (alarmTimer && alarmTimerSet && (alarmTimerSecond == second())) + { + alarmTimer--; +#ifdef DEBUG + if (alarmTimer) + Serial.printf("Timeralarm in %u min.\r\n", alarmTimer); +#endif + } + // Switch on buzzer for timer + if (!alarmTimer && alarmTimerSet) + { + alarmTimerSet = false; + alarmOn = BUZZTIME_TIMER; +#ifdef DEBUG + Serial.println("Timeralarm: on"); +#endif + } +#endif + + // Auto switch modes + if (settings.mySettings.modeChange && (mode == MODE_TIME)) + { + autoModeChangeTimer--; + if (!autoModeChangeTimer) + { +#ifdef DEBUG + Serial.println("Auto modechange. (" + String(autoMode) + ")"); +#endif + autoModeChangeTimer = AUTO_MODECHANGE_TIME; + switch (autoMode) + { + case 0: +#ifdef WEATHER + if (WiFi.isConnected()) + { + setMode(MODE_EXT_TEMP); + } + else + { + WiFi.reconnect(); + setMode(MODE_EXT_TEMP); + } +#endif + autoMode = 1; + break; + case 1: +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + setMode(MODE_TEMP); +#else +#ifdef WEATHER + if (WiFi.isConnected()) + { + setMode(MODE_EXT_TEMP); + } + else + { + WiFi.reconnect(); + setMode(MODE_EXT_TEMP); + } +#endif +#endif + autoMode = 0; + break; + } + } + } + + // Show event in feed +#ifdef EVENT_TIME + if (mode == MODE_TIME) + { + showEventTimer--; + if (!showEventTimer) + { + showEventTimer = EVENT_TIME; + for (uint8_t i = 0; i < (sizeof(events) / sizeof(event_t)); i++) + { + if ((day() == events[i].day) && (month() == events[i].month)) + { + if (events[i].year) + feedText = " " + events[i].text + " (" + String(year() - events[i].year) + ") "; + else + feedText = " " + events[i].text + " "; + feedPosition = 0; + feedColor = events[i].color; +#ifdef DEBUG + Serial.println("Event: \"" + feedText + "\""); +#endif + setMode(MODE_FEED); + } + } + } + } +#endif + } + + //************************************************************************* + // Run always + //************************************************************************* + + if (mode == MODE_FEED) + screenBufferNeedsUpdate = true; + + // Call HTTP- and OTA-handle + webServer.handleClient(); + ArduinoOTA.handle(); + + // Set brightness from LDR and update display (not screenbuffer) at 40Hz. +#ifdef LDR + if (settings.mySettings.useAbc) + { + if ((millis() > iBrightnessMillis + 25) && !testFlag) + { + iBrightnessMillis = millis(); + iTargetBrightness = getBrightnessFromLDR(); + if (brightness < iTargetBrightness) brightness++; + if (brightness > iTargetBrightness) brightness--; + writeScreenBuffer(matrix, settings.mySettings.color, brightness); + } + } +#endif + +#ifdef IR_RECEIVER + // Look for IR commands + if (irrecv.decode(&irDecodeResult)) + { +#ifdef DEBUG_IR + Serial.print("IR signal: 0x"); + serialPrintUint64(irDecodeResult.value, HEX); + Serial.println(); +#endif + switch (irDecodeResult.value) + { + case IR_CODE_ONOFF: + buttonOnOffPressed(); + break; + case IR_CODE_TIME: + buttonTimePressed(); + break; + case IR_CODE_MODE: + buttonModePressed(); + break; + } + irrecv.resume(); + } +#endif + + // Render a new screenbuffer if needed + if (screenBufferNeedsUpdate) + { + screenBufferNeedsUpdate = false; + + // Save old screenbuffer (or not if it's the test pattern) + if (testFlag) + { + for (uint8_t i = 0; i <= 9; i++) matrixOld[i] = 0; + testFlag = false; + } + else + for (uint8_t i = 0; i <= 9; i++) matrixOld[i] = matrix[i]; + + switch (mode) + { + case MODE_TIME: +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) + sunrise_started = false; + sunset_started = false; +#endif + renderer.clearScreenBuffer(matrix); + +#ifdef FRONTCOVER_BINARY + matrix[0] = 0b1111000000000000; + matrix[1] = hour() << 5; + matrix[2] = minute() << 5; + matrix[3] = second() << 5; + matrix[5] = 0b1111000000000000; + matrix[6] = day() << 5; + matrix[7] = month() << 5; + matrix[8] = year() - 2000 << 5; +#else + renderer.setTime(hour(), minute(), matrix); + renderer.setCorners(minute(), matrix); + if (!settings.mySettings.itIs && ((minute() / 5) % 6)) renderer.clearEntryWords(matrix); +#endif +#ifdef BUZZER + if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) renderer.setAlarmLed(matrix); +#endif + break; +#ifdef SHOW_MODE_AMPM + case MODE_AMPM: + renderer.clearScreenBuffer(matrix); + isAM() ? renderer.setSmallText("AM", TEXT_POS_MIDDLE, matrix) : renderer.setSmallText("PM", TEXT_POS_MIDDLE, matrix); + break; +#endif +#ifdef SHOW_MODE_SECONDS + case MODE_SECONDS: + renderer.clearScreenBuffer(matrix); + renderer.setCorners(minute(), matrix); + for (uint8_t i = 0; i <= 6; i++) + { + matrix[1 + i] |= numbersBig[second() / 10][i] << 11; + matrix[1 + i] |= numbersBig[second() % 10][i] << 5; + } + break; +#endif +#ifdef SHOW_MODE_WEEKDAY + case MODE_WEEKDAY: + renderer.clearScreenBuffer(matrix); + renderer.setSmallText(String(sWeekday[weekday()][0]) + String(sWeekday[weekday()][1]), TEXT_POS_MIDDLE, matrix); + break; +#endif +#ifdef SHOW_MODE_DATE + case MODE_DATE: + renderer.clearScreenBuffer(matrix); + if (day() < 10) + renderer.setSmallText(("0" + String(day())), TEXT_POS_TOP, matrix); + else + renderer.setSmallText(String(day()), TEXT_POS_TOP, matrix); + if (month() < 10) + renderer.setSmallText(("0" + String(month())), TEXT_POS_BOTTOM, matrix); + else + renderer.setSmallText(String(month()), TEXT_POS_BOTTOM, matrix); + renderer.setPixelInScreenBuffer(5, 4, matrix); + renderer.setPixelInScreenBuffer(5, 9, matrix); + break; +#endif +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) + case MODE_SUNRISE: + if (!sunrise_started) + { + sunrise_unix = timeZone.toLocal(outdoorWeather.sunrise); + sunrise_started = true; + sunrise_millis = millis(); + save_color_sunrise_sunset = settings.mySettings.color; + } + // if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.333) + if (millis() < sunrise_millis + 1000) + { + settings.mySettings.color = YELLOW; + renderer.clearScreenBuffer(matrix); + // Sunrise screen + matrix[0] = 0b0000000000000000; + matrix[1] = 0b0000000000000000; + matrix[2] = 0b0000000000000000; + matrix[3] = 0b0000000000000000; + matrix[4] = 0b0000000000000000; + matrix[5] = 0b0000111000000000; + matrix[6] = 0b0011111110000000; + matrix[7] = 0b0111111111000000; + matrix[8] = 0b0111111111000000; + matrix[9] = 0b1111111111100000; + } + // else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.666) + else if (millis() < sunrise_millis + 2000) + { + renderer.clearScreenBuffer(matrix); + // Sunrise screen + matrix[0] = 0b0000000000000000; + matrix[1] = 0b0000000000000000; + matrix[2] = 0b0000111000000000; + matrix[3] = 0b0011111110000000; + matrix[4] = 0b0111111111000000; + matrix[5] = 0b0111111111000000; + matrix[6] = 0b1111111111100000; + matrix[7] = 0b1111111111100000; + matrix[8] = 0b0111111111000000; + matrix[9] = 0b0111111111000000; + } + // else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 0.5) + else if (millis() < sunrise_millis + 3000) + { + renderer.clearScreenBuffer(matrix); + // Sunrise screen + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011111110000000; + matrix[2] = 0b0111111111000000; + matrix[3] = 0b0111111111000000; + matrix[4] = 0b1111111111100000; + matrix[5] = 0b1111111111100000; + matrix[6] = 0b0111111111000000; + matrix[7] = 0b0111111111000000; + matrix[8] = 0b0011111110000000; + matrix[9] = 0b0000111000000000; + } + //else if (millis() < sunrise_millis + SUNSET_SUNRISE_SPEED * 1.5) + else if (millis() < sunrise_millis + 4000 + settings.mySettings.timeout * 1000) + { + renderer.clearScreenBuffer(matrix); + renderer.setTime(hour(sunrise_unix), minute(sunrise_unix), matrix); + renderer.setCorners(minute(sunrise_unix), matrix); + renderer.clearEntryWords(matrix); + } + else + { + sunrise_started = false; + settings.mySettings.color = save_color_sunrise_sunset; + setMode(MODE_TIME); + } + break; + + case MODE_SUNSET: + if (!sunset_started) + { + sunset_unix = timeZone.toLocal(outdoorWeather.sunset); + sunset_started = true; + sunset_millis = millis(); + } + + // Matrix is only updatet every second. + // if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.333) + if (millis() < sunset_millis + 1000) + { + settings.mySettings.color = ORANGE; + renderer.clearScreenBuffer(matrix); + // Sunset screen + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011111110000000; + matrix[2] = 0b0111111111000000; + matrix[3] = 0b0111111111000000; + matrix[4] = 0b1111111111100000; + matrix[5] = 0b1111111111100000; + matrix[6] = 0b0111111111000000; + matrix[7] = 0b0111111111000000; + matrix[8] = 0b0011111110000000; + matrix[9] = 0b0000111000000000; + } + // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5 * 0.666) + else if (millis() < sunset_millis + 2000) + { + renderer.clearScreenBuffer(matrix); + // Sunset screen + matrix[0] = 0b0000000000000000; + matrix[1] = 0b0000000000000000; + matrix[2] = 0b0000111000000000; + matrix[3] = 0b0011111110000000; + matrix[4] = 0b0111111111000000; + matrix[5] = 0b0111111111000000; + matrix[6] = 0b1111111111100000; + matrix[7] = 0b1111111111100000; + matrix[8] = 0b0111111111000000; + matrix[9] = 0b0111111111000000; + } + // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 0.5) + else if (millis() < sunset_millis + 3000) + { + renderer.clearScreenBuffer(matrix); + // Sunset screen + matrix[0] = 0b0000000000000000; + matrix[1] = 0b0000000000000000; + matrix[2] = 0b0000000000000000; + matrix[3] = 0b0000000000000000; + matrix[4] = 0b0000000000000000; + matrix[5] = 0b0000111000000000; + matrix[6] = 0b0011111110000000; + matrix[7] = 0b0111111111000000; + matrix[8] = 0b0111111111000000; + matrix[9] = 0b1111111111100000; + } + // else if (millis() < sunset_millis + SUNSET_SUNRISE_SPEED * 1.5) + else if (millis() < sunset_millis + 4000 + settings.mySettings.timeout * 1000) + { + renderer.clearScreenBuffer(matrix); + renderer.setTime(hour(sunset_unix), minute(sunset_unix), matrix); + renderer.setCorners(minute(sunset_unix), matrix); + renderer.clearEntryWords(matrix); + } + else + { + sunset_started = false; + settings.mySettings.color = save_color_sunrise_sunset; + setMode(MODE_TIME); + } + break; +#endif +#ifdef SHOW_MODE_MOONPHASE + case MODE_MOONPHASE: +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) + settings.mySettings.color = save_color_sunrise_sunset; +#endif + renderer.clearScreenBuffer(matrix); + switch (moonphase) + { + case 0: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011000110000000; + matrix[2] = 0b0100000001000000; + matrix[3] = 0b0100000001000000; + matrix[4] = 0b1000000000100000; + matrix[5] = 0b1000000000100000; + matrix[6] = 0b0100000001000000; + matrix[7] = 0b0100000001000000; + matrix[8] = 0b0011000110000000; + matrix[9] = 0b0000111000000000; + break; + case 1: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0000001110000000; + matrix[2] = 0b0000000111000000; + matrix[3] = 0b0000000111000000; + matrix[4] = 0b0000000111100000; + matrix[5] = 0b0000000111100000; + matrix[6] = 0b0000000111000000; + matrix[7] = 0b0000000111000000; + matrix[8] = 0b0000001110000000; + matrix[9] = 0b0000111000000000; + break; + case 2: + matrix[0] = 0b0000011000000000; + matrix[1] = 0b0000011110000000; + matrix[2] = 0b0000011111000000; + matrix[3] = 0b0000011111000000; + matrix[4] = 0b0000011111100000; + matrix[5] = 0b0000011111100000; + matrix[6] = 0b0000011111000000; + matrix[7] = 0b0000011111000000; + matrix[8] = 0b0000011110000000; + matrix[9] = 0b0000011000000000; + break; + case 3: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0001111110000000; + matrix[2] = 0b0001111111000000; + matrix[3] = 0b0001111111000000; + matrix[4] = 0b0001111111100000; + matrix[5] = 0b0001111111100000; + matrix[6] = 0b0001111111000000; + matrix[7] = 0b0001111111000000; + matrix[8] = 0b0001111110000000; + matrix[9] = 0b0000111000000000; + break; + case 4: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011111110000000; + matrix[2] = 0b0111111111000000; + matrix[3] = 0b0111111111000000; + matrix[4] = 0b1111111111100000; + matrix[5] = 0b1111111111100000; + matrix[6] = 0b0111111111000000; + matrix[7] = 0b0111111111000000; + matrix[8] = 0b0011111110000000; + matrix[9] = 0b0000111000000000; + break; + case 5: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011111100000000; + matrix[2] = 0b0111111100000000; + matrix[3] = 0b0111111100000000; + matrix[4] = 0b1111111100000000; + matrix[5] = 0b1111111100000000; + matrix[6] = 0b0111111100000000; + matrix[7] = 0b0111111100000000; + matrix[8] = 0b0011111100000000; + matrix[9] = 0b0000111000000000; + break; + case 6: + matrix[0] = 0b0000110000000000; + matrix[1] = 0b0011110000000000; + matrix[2] = 0b0111110000000000; + matrix[3] = 0b0111110000000000; + matrix[4] = 0b1111110000000000; + matrix[5] = 0b1111110000000000; + matrix[6] = 0b0111110000000000; + matrix[7] = 0b0111110000000000; + matrix[8] = 0b0011110000000000; + matrix[9] = 0b0000110000000000; + break; + case 7: + matrix[0] = 0b0000111000000000; + matrix[1] = 0b0011100000000000; + matrix[2] = 0b0111000000000000; + matrix[3] = 0b0111000000000000; + matrix[4] = 0b1111000000000000; + matrix[5] = 0b1111000000000000; + matrix[6] = 0b0111000000000000; + matrix[7] = 0b0111000000000000; + matrix[8] = 0b0011100000000000; + matrix[9] = 0b0000111000000000; + break; + } + break; +#endif +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + case MODE_TEMP: +#ifdef DEBUG + Serial.println("Room Temperature: " + String(roomTemperature) + " °C"); +#endif + renderer.clearScreenBuffer(matrix); + if (roomTemperature == 0) + { + matrix[0] = 0b0000000001000000; + matrix[1] = 0b0000000010100000; + matrix[2] = 0b0000000010100000; + matrix[3] = 0b0000000011100000; + } + if (roomTemperature > 0) + { + matrix[0] = 0b0000000001000000; + matrix[1] = 0b0100000010100000; + matrix[2] = 0b1110000010100000; + matrix[3] = 0b0100000011100000; + } + if (roomTemperature < 0) + { + matrix[0] = 0b0000000001000000; + matrix[1] = 0b0000000010100000; + matrix[2] = 0b1110000010100000; + matrix[3] = 0b0000000011100000; + } + renderer.setSmallText(String(int(abs(roomTemperature) + 0.5)), TEXT_POS_BOTTOM, matrix); + break; +#ifdef SENSOR_DHT22 + case MODE_HUMIDITY: +#ifdef DEBUG + Serial.println("Room Humidity: " + String(roomHumidity) + " %rH"); +#endif + renderer.clearScreenBuffer(matrix); + renderer.setSmallText(String(int(roomHumidity + 0.5)), TEXT_POS_TOP, matrix); + matrix[6] = 0b0100100001000000; + matrix[7] = 0b0001000010100000; + matrix[8] = 0b0010000010100000; + matrix[9] = 0b0100100011100000; + break; +#endif +#endif +#ifdef WEATHER + case MODE_EXT_TEMP: +#ifdef DEBUG + Serial.println("Outdoor temperature: " + String(outdoorWeather.temperature) + " °C"); +#endif + renderer.clearScreenBuffer(matrix); + if (outdoorWeather.temperature > 0) + { + matrix[1] = 0b0100000000000000; + matrix[2] = 0b1110000000000000; + matrix[3] = 0b0100000000000000; + } + if (outdoorWeather.temperature < 0) + matrix[2] = 0b1110000000000000; + renderer.setSmallText(String(int(abs(outdoorWeather.temperature) + 0.5)), TEXT_POS_BOTTOM, matrix); + break; + case MODE_EXT_HUMIDITY: +#ifdef DEBUG + Serial.println("Outdoor humidity: " + String(outdoorWeather.humidity) + " %rH"); +#endif + renderer.clearScreenBuffer(matrix); + if (outdoorWeather.humidity < 100) + renderer.setSmallText(String(outdoorWeather.humidity), TEXT_POS_TOP, matrix); + else + { + matrix[0] = 0b0010111011100000; + matrix[1] = 0b0110101010100000; + matrix[2] = 0b0010101010100000; + matrix[3] = 0b0010101010100000; + matrix[4] = 0b0010111011100000; + } + matrix[6] = 0b0100100000000000; + matrix[7] = 0b0001000000000000; + matrix[8] = 0b0010000000000000; + matrix[9] = 0b0100100000000000; + break; +#endif +#ifdef BUZZER + case MODE_TIMER: + renderer.clearScreenBuffer(matrix); + renderer.setSmallText("TI", TEXT_POS_TOP, matrix); + renderer.setSmallText(String(alarmTimer), TEXT_POS_BOTTOM, matrix); + break; +#endif +#ifdef SHOW_MODE_TEST + case MODE_TEST: + renderer.clearScreenBuffer(matrix); + if (testColumn == 10) + testColumn = 0; + matrix[testColumn] = 0b1111111111110000; + testColumn++; + break; + case MODE_RED: + case MODE_GREEN: + case MODE_BLUE: + case MODE_WHITE: + renderer.setAllScreenBuffer(matrix); + testFlag = true; + break; +#endif + case MODE_BLANK: + renderer.clearScreenBuffer(matrix); + break; + case MODE_FEED: + for (uint8_t y = 0; y <= 5; y++) + { + renderer.clearScreenBuffer(matrix); + for (uint8_t z = 0; z <= 6; z++) + { + matrix[2 + z] |= (lettersBig[feedText[feedPosition] - 32][z] << (11 + y)) & 0b1111111111100000; + matrix[2 + z] |= (lettersBig[feedText[feedPosition + 1] - 32][z] << (5 + y)) & 0b1111111111100000; + matrix[2 + z] |= (lettersBig[feedText[feedPosition + 2] - 32][z] << (y - 1)) & 0b1111111111100000; + } + writeScreenBuffer(matrix, feedColor, brightness); + delay(120); + } + feedPosition++; + if (feedPosition == feedText.length() - 2) + { + feedPosition = 0; + setMode(MODE_TIME); + } + break; + } + + // turn off LED behind IR-sensor +#ifdef IR_LETTER_OFF + renderer.unsetPixelInScreenBuffer(IR_LETTER_X, IR_LETTER_Y - 1, matrix); +#endif + + //debugScreenBuffer(matrixOld); +#ifdef DEBUG_MATRIX + debugScreenBuffer(matrix); +#endif + + // write screenbuffer to display + switch (mode) + { + case MODE_TIME: + case MODE_BLANK: + if (settings.mySettings.transition == TRANSITION_NORMAL) + writeScreenBuffer(matrix, settings.mySettings.color, brightness); + if (settings.mySettings.transition == TRANSITION_FADE) + writeScreenBufferFade(matrixOld, matrix, settings.mySettings.color, brightness); + if (settings.mySettings.transition == TRANSITION_MOVEUP) + { + if (minute() % 5 == 0) + moveScreenBufferUp(matrixOld, matrix, settings.mySettings.color, brightness); + else + writeScreenBuffer(matrix, settings.mySettings.color, brightness); + } + break; +#ifdef SHOW_MODE_TEST + case MODE_RED: + writeScreenBuffer(matrix, RED, TEST_BRIGHTNESS); + break; + case MODE_GREEN: + writeScreenBuffer(matrix, GREEN, TEST_BRIGHTNESS); + break; + case MODE_BLUE: + writeScreenBuffer(matrix, BLUE, TEST_BRIGHTNESS); + break; + case MODE_WHITE: + writeScreenBuffer(matrix, WHITE, TEST_BRIGHTNESS); + break; +#endif + case MODE_FEED: + writeScreenBuffer(matrix, feedColor, brightness); + break; + default: + if (runTransitionOnce) + { + if (settings.mySettings.transition == TRANSITION_NORMAL) + writeScreenBuffer(matrix, settings.mySettings.color, brightness); + if (settings.mySettings.transition == TRANSITION_FADE) + writeScreenBufferFade(matrixOld, matrix, settings.mySettings.color, brightness); + if (settings.mySettings.transition == TRANSITION_MOVEUP) + moveScreenBufferUp(matrixOld, matrix, settings.mySettings.color, brightness); + runTransitionOnce = false; + testColumn = 0; + } + else + writeScreenBuffer(matrix, settings.mySettings.color, brightness); + break; + } + } + + // Wait for mode timeout then switch back to time + if ((millis() > (modeTimeout + settings.mySettings.timeout * 1000)) && modeTimeout) + { + digitalWrite(PIN_MODE_BUTTON_LED,LOW); +// #if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) +// sunrise_started = false; +// sunset_started = false; +// #endif + setMode(MODE_TIME); + } + +#ifdef DEBUG_FPS + debugFps(); +#endif +} // loop() + +//***************************************************************************** +// Transitions +//***************************************************************************** + +void writeScreenBuffer(uint16_t screenBuffer[], uint8_t color, uint8_t brightness) +{ + ledDriver.clear(); + for (uint8_t y = 0; y <= 9; y++) + { + for (uint8_t x = 0; x <= 10; x++) + { + if (bitRead(screenBuffer[y], 15 - x)) + ledDriver.setPixel(x, y, color, brightness); + } + } + + // Corner LEDs + for (uint8_t y = 0; y <= 3; y++) + { + if (bitRead(screenBuffer[y], 4)) + ledDriver.setPixel(110 + y, color, brightness); + } + + // Alarm LED +#ifdef BUZZER + if (bitRead(screenBuffer[4], 4)) + { +#ifdef ALARM_LED_COLOR +#ifdef ABUSE_CORNER_LED_FOR_ALARM + if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) + ledDriver.setPixel(111, ALARM_LED_COLOR, brightness); + else + if (bitRead(screenBuffer[1], 4)) + ledDriver.setPixel(111, color, brightness); +#else + ledDriver.setPixel(114, ALARM_LED_COLOR, brightness); +#endif +#else + ledDriver.setPixel(114, color, brightness); +#endif + } +#endif + + ledDriver.show(); +} // writeScreenBuffer + +void moveScreenBufferUp(uint16_t screenBufferOld[], uint16_t screenBufferNew[], uint8_t color, uint8_t brightness) +{ + for (uint8_t z = 0; z <= 9; z++) + { + for (uint8_t i = 0; i <= 8; i++) + screenBufferOld[i] = screenBufferOld[i + 1]; + screenBufferOld[9] = screenBufferNew[z]; + writeScreenBuffer(screenBufferOld, color, brightness); + webServer.handleClient(); + delay(50); + } +} // moveScreenBufferUp + +void writeScreenBufferFade(uint16_t screenBufferOld[], uint16_t screenBufferNew[], uint8_t color, uint8_t brightness) +{ + ledDriver.clear(); + uint8_t brightnessBuffer[10][12] = {}; + + // Copy old matrix to buffer + for (uint8_t y = 0; y <= 9; y++) + { + for (uint8_t x = 0; x <= 11; x++) + { + if (bitRead(screenBufferOld[y], 15 - x)) + brightnessBuffer[y][x] = brightness; + } + } + + // Fade old to new matrix + for (uint8_t i = 0; i < brightness; i++) + { + for (uint8_t y = 0; y <= 9; y++) + { + for (uint8_t x = 0; x <= 11; x++) + { + ESP.wdtFeed(); + if (!(bitRead(screenBufferOld[y], 15 - x)) && (bitRead(screenBufferNew[y], 15 - x))) + brightnessBuffer[y][x]++; + if ((bitRead(screenBufferOld[y], 15 - x)) && !(bitRead(screenBufferNew[y], 15 - x))) + brightnessBuffer[y][x]--; + ledDriver.setPixel(x, y, color, brightnessBuffer[y][x]); + } + } + + // Corner LEDs + for (uint8_t y = 0; y <= 3; y++) + ledDriver.setPixel(110 + y, color, brightnessBuffer[y][11]); + + // Alarm LED +#ifdef BUZZER +#ifdef ALARM_LED_COLOR +#ifdef ABUSE_CORNER_LED_FOR_ALARM + if (settings.mySettings.alarm1 || settings.mySettings.alarm2 || alarmTimerSet) + ledDriver.setPixel(111, ALARM_LED_COLOR, brightnessBuffer[4][11]); + else + ledDriver.setPixel(111, color, brightnessBuffer[1][11]); +#else + ledDriver.setPixel(114, ALARM_LED_COLOR, brightnessBuffer[4][11]); +#endif +#else + ledDriver.setPixel(114, color, brightnessBuffer[4][11]); +#endif +#endif + webServer.handleClient(); + ledDriver.show(); + } +} // writeScreenBufferFade + +//***************************************************************************** +// "On/off" pressed +//***************************************************************************** + +void buttonOnOffPressed() +{ +#ifdef DEBUG + Serial.println("On/off pressed."); +#endif + mode == MODE_BLANK ? setLedsOn() : setLedsOff(); +} + +//***************************************************************************** +// "Time" pressed +//***************************************************************************** + +void buttonTimePressed() +{ +#ifdef DEBUG + Serial.println("Time pressed."); +#endif + + // Switch off alarm +#ifdef BUZZER + if (alarmOn) + { +#ifdef DEBUG + Serial.println("Alarm: off"); +#endif + digitalWrite(PIN_BUZZER, LOW); + alarmOn = false; + } +#endif +#if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) + settings.mySettings.color = save_color_sunrise_sunset; +#endif + modeTimeout = 0; + setMode(MODE_TIME); +} + +//***************************************************************************** +// "Mode" pressed +//***************************************************************************** + +void buttonModePressed() +{ + digitalWrite(PIN_MODE_BUTTON_LED, HIGH); +#ifdef DEBUG + Serial.println("Mode pressed."); +#endif + + // Switch off alarm +#ifdef BUZZER + if (alarmOn) + { +#ifdef DEBUG + Serial.println("Alarm: off"); +#endif + digitalWrite(PIN_BUZZER, LOW); + alarmOn = false; + setMode(MODE_TIME); + return; + } +#endif + setMode(mode++); +} + +//***************************************************************************** +// Set mode +//***************************************************************************** + +void setMode(Mode newMode) +{ + screenBufferNeedsUpdate = true; + runTransitionOnce = true; + lastMode = mode; + mode = newMode; + + // set timeout for selected mode + switch (mode) + { +#ifdef SHOW_MODE_AMPM + case MODE_AMPM: +#endif +#ifdef SHOW_MODE_SECONDS + case MODE_SECONDS: +#endif +#ifdef SHOW_MODE_WEEKDAY + case MODE_WEEKDAY: +#endif +#ifdef SHOW_MODE_DATE + case MODE_DATE: +#endif +// #if defined(SHOW_MODE_SUNRISE_SUNSET) && defined(WEATHER) +// case MODE_SUNRISE: +// case MODE_SUNSET: +// #endif +#ifdef SHOW_MODE_MOONPHASE + case MODE_MOONPHASE: +#endif +#if defined(RTC_BACKUP) && !defined(SENSOR_DHT22) + case MODE_TEMP: +#endif +#ifdef SENSOR_DHT22 + case MODE_TEMP: + case MODE_HUMIDITY: +#endif +#ifdef WEATHER + case MODE_EXT_TEMP: + case MODE_EXT_HUMIDITY: +#endif + modeTimeout = millis(); + break; + default: + modeTimeout = 0; + break; + } +} + +//***************************************************************************** +// Get brightness from LDR +//***************************************************************************** + +#ifdef LDR +uint8_t getBrightnessFromLDR() +{ +#ifdef LDR_IS_INVERSE + ldrValue = 1024 - analogRead(PIN_LDR); +#else + ldrValue = analogRead(PIN_LDR); +#endif + if (ldrValue < minLdrValue) + minLdrValue = ldrValue; + if (ldrValue > maxLdrValue) + maxLdrValue = ldrValue; + if ((ldrValue >= (lastLdrValue + 10)) || (ldrValue <= (lastLdrValue - 10))) // Hysteresis is 10 + { + lastLdrValue = ldrValue; + return (uint8_t)map(ldrValue, minLdrValue, maxLdrValue, MIN_BRIGHTNESS, maxBrightness); + } + return iTargetBrightness; +} +#endif + +//***************************************************************************** +// Get update info from server +//***************************************************************************** + +#ifdef UPDATE_INFOSERVER +void getUpdateInfo() +{ + WiFiClient wifiClient; + HttpClient httpClient = HttpClient(wifiClient, UPDATE_INFOSERVER, 80); + httpClient.get(UPDATE_INFOFILE); + if (httpClient.responseStatusCode() == 200) + { + String response = httpClient.responseBody(); + response.trim(); + JSONVar updateArray = JSON.parse(response); + if (JSON.typeof(updateArray) == "undefined") + { + #ifdef DEBUG + Serial.println("Parsing updateArray failed!"); + #endif + return; + } + updateInfo = (int)updateArray["channel"]["unstable"]["version"]; + } +#ifdef DEBUG + updateInfo > int(FIRMWARE_VERSION) ? Serial.println("Firmwareupdate available! (" + String(updateInfo) + ")") : Serial.println("Firmware is uptodate."); +#endif +} +#endif + +//***************************************************************************** +// Get room conditions +//***************************************************************************** + +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) +void getRoomConditions() +{ +#if defined(RTC_BACKUP) && !defined(SENSOR_DHT22) + roomTemperature = RTC.temperature() / 4.0 + RTC_TEMPERATURE_OFFSET; +#ifdef DEBUG + Serial.println("Temperature (RTC): " + String(roomTemperature) + "° C"); +#endif +#endif +#ifdef SENSOR_DHT22 + float dhtTemperature = dht.readTemperature(); + float dhtHumidity = dht.readHumidity(); + if (!isnan(dhtTemperature) && !isnan(dhtHumidity)) + { + errorCounterDHT = 0; + roomTemperature = dhtTemperature + DHT_TEMPERATURE_OFFSET; + roomHumidity = dhtHumidity + DHT_HUMIDITY_OFFSET; +#ifdef DEBUG + Serial.println("Temperature (DHT): " + String(roomTemperature) + " °C"); + Serial.println("Humidity (DHT): " + String(roomHumidity) + " %rH"); +#endif + } + else + { + if (errorCounterDHT < 255) + errorCounterDHT++; +#ifdef DEBUG + Serial.printf("Error (DHT): %u\r\n", errorCounterDHT); +#endif + } +#endif +} +#endif + +//***************************************************************************** +// Misc +//***************************************************************************** + +#ifdef MODE_BUTTON +ICACHE_RAM_ATTR void buttonModeInterrupt() +{ + if (millis() > lastButtonPress + 250) + { + lastButtonPress = millis(); + buttonModePressed(); + } +} +#endif + +#ifdef ONOFF_BUTTON +ICACHE_RAM_ATTR void buttonOnOffInterrupt() +{ + if (millis() > lastButtonPress + 250) + { + lastButtonPress = millis(); + buttonOnOffPressed(); + } +} +#endif + +#ifdef TIME_BUTTON +ICACHE_RAM_ATTR void buttonTimeInterrupt() +{ + if (millis() > lastButtonPress + 250) + { + lastButtonPress = millis(); + buttonTimePressed(); + } +} +#endif + +// Switch off LEDs +void setLedsOff() +{ +#ifdef DEBUG + Serial.println("LEDs: off"); +#endif + setMode(MODE_BLANK); +} + +// Switch on LEDs +void setLedsOn() +{ +#ifdef DEBUG + Serial.println("LEDs: on"); +#endif + setMode(lastMode); +} + +// Calculate moonphase +#ifdef SHOW_MODE_MOONPHASE +int getMoonphase(int y, int m, int d) +{ + int b; + int c; + int e; + double jd; + if (m < 3) { + y--; + m += 12; + } + ++m; + c = 365.25 * y; + e = 30.6 * m; + jd = c + e + d - 694039.09; // jd is total days elapsed + jd /= 29.53; // divide by the moon cycle (29.53 days) + b = jd; // int(jd) -> b, take integer part of jd + jd -= b; // subtract integer part to leave fractional part of original jd + b = jd * 8 + 0.5; // scale fraction from 0-8 and round by adding 0.5 + b = b & 7; // 0 and 8 are the same so turn 8 into 0 + return b; +} +#endif + +// Write screenbuffer to console +#ifdef DEBUG_MATRIX +void debugScreenBuffer(uint16_t screenBuffer[]) +{ + const char buchstabensalat[][12] = + { + { 'E', 'S', 'K', 'I', 'S', 'T', 'A', 'F', 'U', 'N', 'F', '1' }, + { 'Z', 'E', 'H', 'N', 'Z', 'W', 'A', 'N', 'Z', 'I', 'G', '2' }, + { 'D', 'R', 'E', 'I', 'V', 'I', 'E', 'R', 'T', 'E', 'L', '3' }, + { 'V', 'O', 'R', 'F', 'U', 'N', 'K', 'N', 'A', 'C', 'H', '4' }, + { 'H', 'A', 'L', 'B', 'A', 'E', 'L', 'F', 'U', 'N', 'F', 'A' }, + { 'E', 'I', 'N', 'S', 'X', 'A', 'M', 'Z', 'W', 'E', 'I', ' ' }, + { 'D', 'R', 'E', 'I', 'P', 'M', 'J', 'V', 'I', 'E', 'R', ' ' }, + { 'S', 'E', 'C', 'H', 'S', 'N', 'L', 'A', 'C', 'H', 'T', ' ' }, + { 'S', 'I', 'E', 'B', 'E', 'N', 'Z', 'W', 'O', 'L', 'F', ' ' }, + { 'Z', 'E', 'H', 'N', 'E', 'U', 'N', 'K', 'U', 'H', 'R', ' ' } + }; + //Serial.println("\033[0;0H"); // set cursor to 0, 0 position + Serial.println(" -----------"); + for (uint8_t y = 0; y <= 9; y++) + { + Serial.print('|'); + for (uint8_t x = 0; x <= 10; x++) + Serial.print((bitRead(screenBuffer[y], 15 - x) ? buchstabensalat[y][x] : ' ')); + Serial.print('|'); + Serial.println((bitRead(screenBuffer[y], 4) ? buchstabensalat[y][11] : ' ')); + } + Serial.println(" -----------"); +} +#endif + +// Write FPS to console +#ifdef DEBUG_FPS +void debugFps() +{ + static uint16_t frames; + static uint32_t lastFpsCheck; + frames++; + //if ((millis() % 1000 == 0) && (millis() != lastFpsCheck)) + if (millis() % 1000 == 0) + { + //lastFpsCheck = millis(); + Serial.printf("FPS: %u\r\n", frames); + frames = 0; + } +} +#endif + +//***************************************************************************** +// Webserver +//***************************************************************************** + +void setupWebServer() +{ + webServer.onNotFound(handleNotFound); + webServer.on("/", handleRoot); + webServer.on("/handleButtonOnOff", []() { buttonOnOffPressed(); callRoot(); }); + webServer.on("/handleButtonSettings", handleButtonSettings); + webServer.on("/handleButtonMode", []() { buttonModePressed(); callRoot(); }); + webServer.on("/handleButtonTime", []() { buttonTimePressed(); callRoot(); }); + webServer.on("/commitSettings", handleCommitSettings); + webServer.on("/reset", handleReset); + webServer.on("/setEvent", handleSetEvent); + webServer.on("/showText", handleShowText); + webServer.on("/control", handleControl); + webServer.begin(); +} + +void callRoot() +{ + webServer.send(200, "text/html", ""); +} + +// Page 404 +void handleNotFound() +{ + webServer.send(404, "text/plain", "404 - File Not Found."); +} + +// Page / +void handleRoot() +{ + String message = "" + "" + "" + "" + String(WEBSITE_TITLE) + "" + "" + "" + "" + "" + "" + "" + "

" + String(WEBSITE_TITLE) + "

"; +#ifdef DEDICATION + message += DEDICATION; + message += "

"; +#endif + if (mode == MODE_BLANK) + message += ""; + else + message += ""; + message += "" + "

" + "" + ""; +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + message += "

"; + message += "
" + String(roomTemperature) + "°C / " + String(roomTemperature * 1.8 + 32.0) + "°F"; +#endif +#ifdef SENSOR_DHT22 + message += "
" + String(roomHumidity) + "%rH" + "
"; + if (roomHumidity < 30) + message += ""; + else + message += ""; + if ((roomHumidity >= 30) && (roomHumidity < 40)) + message += " "; + else + message += " "; + if ((roomHumidity >= 40) && (roomHumidity <= 50)) + message += " "; + else + message += " "; + if ((roomHumidity > 50) && (roomHumidity < 60)) + message += " "; + else + message += " "; + if (roomHumidity >= 60) + message += " "; + else + message += " "; + message += ""; +#endif +#ifdef WEATHER + message += "

" + "
" + String(outdoorWeather.temperature) + "°C / " + String(outdoorWeather.temperature * 1.8 + 32.0) + "°F" +\ + "
" + String(outdoorWeather.humidity) + "%rH" +\ + "
" + String(outdoorWeather.pressure) + " hPa / " + String(outdoorWeather.pressure / 33.865) + " inHg" +\ + "
" + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunrise)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunrise)))) +\ + " " + padStringZeros(String(hour(timeZone.toLocal(outdoorWeather.sunset)))) + ":" + padStringZeros(String(minute(timeZone.toLocal(outdoorWeather.sunset)))); +#endif + message += "" + "

Qlockwork was with by ch570512" + "
Firmware: " + String(FIRMWARE_VERSION); +#ifdef UPDATE_INFOSERVER + if (updateInfo > int(FIRMWARE_VERSION)) + message += "
Firmwareupdate available! (" + String(updateInfo) + ")"; +#endif +#ifdef DEBUG_WEB + time_t tempEspTime = now(); + message += "

Time: " + String(hour(tempEspTime)) + ":"; + if (minute(tempEspTime) < 10) + message += "0"; + message += String(minute(tempEspTime)); + if (timeZone.locIsDST(now())) + message += " (DST)"; + message += " up " + String(int(upTime / 86400)) + " days, " + String(hour(upTime)) + ":"; + if (minute(upTime) < 10) + message += "0"; + message += String(minute(upTime)); + message += "
" + String(dayStr(weekday(tempEspTime))) + ", " + String(monthStr(month(tempEspTime))) + " " + String(day(tempEspTime)) + ". " + String(year(tempEspTime)); + message += "
Moonphase: " + String(moonphase); + message += "
Free RAM: " + String(ESP.getFreeHeap()) + " bytes"; + message += "
RSSI: " + String(WiFi.RSSI()); +#ifdef LDR + message += "
Brightness: " + String(brightness) + " (ABC: "; + settings.mySettings.useAbc ? message += "enabled" : message += "disabled"; + message += ", min: " + String(MIN_BRIGHTNESS) + ", max : " + String(maxBrightness) + ")"; + message += "
LDR: " + String(ldrValue) + " (min: " + String(minLdrValue) + ", max: " + String(maxLdrValue) + ")"; +#endif + message += "
Error (NTP): " + String(errorCounterNTP); +#ifdef SENSOR_DHT22 + message += "
Error (DHT): " + String(errorCounterDHT); +#endif +#ifdef WEATHER + message += "
Error (MeteoWeather): " + String(errorCounterOutdoorWeather); +#endif + message += "
Reset reason: " + ESP.getResetReason(); + message += "
Flags: "; +#ifdef RTC_BACKUP + message += "RTC "; +#else + message += "RTC "; +#endif +#ifdef SENSOR_DHT22 + message += "DHT22 "; +#else + message += "DHT22 "; +#endif +#ifdef LDR + message += "LDR "; +#else + message += "LDR "; +#endif +#ifdef BUZZER + message += "BUZZER "; +#else + message += "BUZZER "; +#endif +#ifdef IR_RECEIVER + message += "IR_RECEIVER "; +#else + message += "IR_RECEIVER "; +#endif +#ifdef ESP_LED + message += "ESP_LED "; +#else + message += "ESP_LED "; +#endif +#if defined(ONOFF_BUTTON) || defined(MODE_BUTTON) || defined(TIME_BUTTON) + message += "BUTTONS "; +#else + message += "BUTTONS "; +#endif +#endif + message += "
"; + webServer.send(200, "text/html", message); +} + +// Page settings +void handleButtonSettings() +{ +#ifdef DEBUG + Serial.println("Settings pressed."); +#endif + String message = "" + "" + "" + "" + String(WEBSITE_TITLE) + " " TXT_SETTINGS "" + "" + "" + "" + "" + "" + "" + "

" + String(WEBSITE_TITLE) + " " TXT_SETTINGS "

" + "
" + ""; + // ------------------------------------------------------------------------ +#ifdef BUZZER + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; +#endif + // ------------------------------------------------------------------------ +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + message += ""; +#endif + // ------------------------------------------------------------------------ +#ifdef LDR + message += ""; +#endif + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ +#ifdef WEATHER + message += ""; +#endif + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ +#ifndef FRONTCOVER_BINARY + message += ""; +#endif + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += ""; + // ------------------------------------------------------------------------ + message += "
" + TXT_ALARM + " 1" + "" + " h

" + "
" + TXT_ALARM + " 2" + "" + " h

" + "
" + TXT_TIMER + "" + " " TXT_MINUTES + "
" + TXT_HOURBEEP + "" + "
" + "Show temperature" + "" + "
" + "ABC" + "" + "
" + "Brightness during daytime" + "" + " %" + "
" + "Brightness during nighttime" + "" + " %" + "
" + "Color" + "" + "" + "
" + "Colorchange" + "" + "
" + "Transition" + "" + "
" + "Timeout" + "" + " sec." + "
" + "Night off" + "" + "" + " h" + "
" + "Day on" + "" + "" + " h" + "
" + "Show \"It is\"" + "" + "
" + "Set date/time" + "" + "" + "
" + "
" + "
"; + webServer.send(200, "text/html", message); +} + +void handleCommitSettings() +{ +#ifdef DEBUG + Serial.println("Commit settings pressed."); +#endif + // ------------------------------------------------------------------------ +#ifdef BUZZER + time_t alarmTimeFromWeb = 0; + webServer.arg("a1") == "0" ? settings.mySettings.alarm1 = false : settings.mySettings.alarm1 = true; + alarmTimeFromWeb = webServer.arg("a1t").substring(0, 2).toInt() * 3600 + webServer.arg("a1t").substring(3, 5).toInt() * 60; + if (settings.mySettings.alarm1Time != alarmTimeFromWeb) + settings.mySettings.alarm1 = true; + settings.mySettings.alarm1Time = alarmTimeFromWeb; + settings.mySettings.alarm1Weekdays = + webServer.arg("a1w1").toInt() + + webServer.arg("a1w2").toInt() + + webServer.arg("a1w3").toInt() + + webServer.arg("a1w4").toInt() + + webServer.arg("a1w5").toInt() + + webServer.arg("a1w6").toInt() + + webServer.arg("a1w7").toInt(); + // ------------------------------------------------------------------------ + webServer.arg("a2") == "0" ? settings.mySettings.alarm2 = false : settings.mySettings.alarm2 = true; + alarmTimeFromWeb = webServer.arg("a2t").substring(0, 2).toInt() * 3600 + webServer.arg("a2t").substring(3, 5).toInt() * 60; + if (settings.mySettings.alarm2Time != alarmTimeFromWeb) + settings.mySettings.alarm2 = true; + settings.mySettings.alarm2Time = alarmTimeFromWeb; + settings.mySettings.alarm2Weekdays = + webServer.arg("a2w1").toInt() + + webServer.arg("a2w2").toInt() + + webServer.arg("a2w3").toInt() + + webServer.arg("a2w4").toInt() + + webServer.arg("a2w5").toInt() + + webServer.arg("a2w6").toInt() + + webServer.arg("a2w7").toInt(); + // ------------------------------------------------------------------------ + webServer.arg("hb") == "0" ? settings.mySettings.hourBeep = false : settings.mySettings.hourBeep = true; + // ------------------------------------------------------------------------ + if (webServer.arg("ti").toInt()) { + alarmTimer = webServer.arg("ti").toInt(); + alarmTimerSecond = second(); + alarmTimerSet = true; + setMode(MODE_TIMER); +#ifdef DEBUG + Serial.println("Timer started."); +#endif + } + else + { + if (alarmTimerSet) + { + alarmTimer = 0; + alarmTimerSecond = 0; + alarmTimerSet = false; + setMode(MODE_TIME); +#ifdef DEBUG + Serial.println("Timer stopped."); +#endif + } + } +#endif + // ------------------------------------------------------------------------ +#if defined(RTC_BACKUP) || defined(SENSOR_DHT22) + webServer.arg("mc") == "0" ? settings.mySettings.modeChange = false : settings.mySettings.modeChange = true; +#endif + // ------------------------------------------------------------------------ +#ifdef LDR + if (webServer.arg("ab") == "0") + { + settings.mySettings.useAbc = false; + brightness = maxBrightness_during_daytime; + } + else + settings.mySettings.useAbc = true; +#endif + // ------------------------------------------------------------------------ + settings.mySettings.brightness_during_daytime = webServer.arg("br_day").toInt(); + maxBrightness_during_daytime = map(settings.mySettings.brightness_during_daytime, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); + brightness = maxBrightness_during_daytime; +#ifdef WEATHER + settings.mySettings.brightness_during_nighttime = webServer.arg("br_night").toInt(); + maxBrightness_during_nighttime = map(settings.mySettings.brightness_during_nighttime, 0, 100, MIN_BRIGHTNESS, MAX_BRIGHTNESS); + brightness_during_nighttime = maxBrightness_during_nighttime; + if (outdoorWeather.isDay) + { + brightness = maxBrightness_during_daytime; + } + else + { + brightness = maxBrightness_during_nighttime; + } +#endif + // ------------------------------------------------------------------------ + settings.mySettings.color = webServer.arg("co").toInt(); + // ------------------------------------------------------------------------ + switch (webServer.arg("cc").toInt()) + { + case 0: + settings.mySettings.colorChange = COLORCHANGE_NO; + break; + case 1: + settings.mySettings.colorChange = COLORCHANGE_FIVE; + break; + case 2: + settings.mySettings.colorChange = COLORCHANGE_HOUR; + break; + case 3: + settings.mySettings.colorChange = COLORCHANGE_DAY; + break; + } + // ------------------------------------------------------------------------ + switch (webServer.arg("tr").toInt()) + { + case 0: + settings.mySettings.transition = TRANSITION_NORMAL; + break; + case 1: + settings.mySettings.transition = TRANSITION_MOVEUP; + break; + case 2: + settings.mySettings.transition = TRANSITION_FADE; + break; + } + // ------------------------------------------------------------------------ + settings.mySettings.timeout = webServer.arg("to").toInt(); + // ------------------------------------------------------------------------ + settings.mySettings.nightOffTime = webServer.arg("no").substring(0, 2).toInt() * 3600 + webServer.arg("no").substring(3, 5).toInt() * 60; + // ------------------------------------------------------------------------ + settings.mySettings.dayOnTime = webServer.arg("do").substring(0, 2).toInt() * 3600 + webServer.arg("do").substring(3, 5).toInt() * 60; + // ------------------------------------------------------------------------ + webServer.arg("ii") == "0" ? settings.mySettings.itIs = false : settings.mySettings.itIs = true; + // ------------------------------------------------------------------------ + if (webServer.arg("st").length()) + { + Serial.println(webServer.arg("st")); + setTime(webServer.arg("st").substring(11, 13).toInt(), webServer.arg("st").substring(14, 16).toInt(), 0, webServer.arg("st").substring(8, 10).toInt(), webServer.arg("st").substring(5, 7).toInt(), webServer.arg("st").substring(0, 4).toInt()); +#ifdef RTC_BACKUP + RTC.set(now()); +#endif + } + // ------------------------------------------------------------------------ + settings.saveToEEPROM(); + callRoot(); + screenBufferNeedsUpdate = true; +} + +// Page reset +void handleReset() +{ + webServer.send(200, "text/plain", "OK. I'll be back!"); + ESP.restart(); +} + +// Page setEvent +void handleSetEvent() +{ + events[0].day = webServer.arg("day").toInt(); + events[0].month = webServer.arg("month").toInt(); + events[0].text = webServer.arg("text").substring(0, 40); + events[0].color = (eColor)webServer.arg("color").toInt();; + webServer.send(200, "text/plain", "OK."); + +#ifdef DEBUG + Serial.println("Event set: " + String(events[0].day) + "." + String(events[0].month) + ". " + events[0].text); +#endif +} + +// Page showText +void handleShowText() +{ + uint8_t feedBuzzer = webServer.arg("buzzer").toInt(); + feedColor = webServer.arg("color").toInt(); + feedText = " " + webServer.arg("text").substring(0, 80) + " "; + feedPosition = 0; + webServer.send(200, "text/plain", "OK."); + +#ifdef DEBUG + Serial.println("Show text: " + webServer.arg("text").substring(0, 80)); +#endif + +#ifdef BUZZER + for (uint8_t i = 0; i < feedBuzzer; i++) + { + digitalWrite(PIN_BUZZER, HIGH); + delay(75); + digitalWrite(PIN_BUZZER, LOW); + delay(100); + } +#endif + + setMode(MODE_FEED); +} + +void handleControl() +{ + setMode((Mode)webServer.arg("mode").toInt()); + webServer.send(200, "text/plain", "OK."); +} + +String padStringZeros(String input) +{ + return (input.length() > 1) ? input : "0" + input; } \ No newline at end of file diff --git a/Readme.txt b/src/Readme.txt similarity index 94% rename from Readme.txt rename to src/Readme.txt index c744c5e..95c207e 100644 --- a/Readme.txt +++ b/src/Readme.txt @@ -61,7 +61,8 @@ Webpage to control and configure the clock via WiFi. Adaptive brightness control when using an LDR. 3 transitions for timechange. Indoor temperature from RTC or temperature and humidity from DHT sensor. -Outdoor temperature and humidity from MeteoWeather. +Outdoor temperature and humidity from MeteoWeather. You need WEATHER from MeteoWeather to use this feature. + Visualisation of moonphase. Show sunrise and sunset times with animation. Textfeed for events and infos, local and over the web. @@ -71,6 +72,7 @@ Support for 16 frontcovers (Original and DIY) in 6 languages. 2 Alarms with weekday selection. NTP timesync with timezone support. Automatic adjustment of daylight saving time. +Different brightnesses can be set for day- and nighttime. USB and Over-the-air firmware updates. ****************************************************************************** @@ -103,8 +105,9 @@ Needed libraries: (recommended/tested versions in brackets) Arduino IDE for Windows (1.8.19) esp8266 by ESP8266 Community (3.0.2) Arduino_JSON by Arduino (0.1.0) -ArduinoJason by bblanchon (7.1.0) +ArduinoJson by bblanchon (7.1.0) Adafruit NeoPixel by Adafruit (1.10.4) + Adafruit Unified Sensor by Adafruit (1.1.5) ArduinoHttpClient by Arduino (0.4.0) ArduinoOTA by Juraj Andressy (1.0.7) @@ -187,6 +190,8 @@ ABC: Enable (on) or disable (off) adaptive bright Brightness will adjust itself in the range of MIN_BRIGHTNESS and brightness. Brightness: Brightness of the LEDs in percent. The range is MIN_BRIGHTNESS to MAX_BRIGHTNESS. If ABC is enabled this is the maximum achievable brightness. +Brightness during nighttime: Brightness level at nighttime. Nighttime starts at sunset + NIGHT_BRIGHTNESS_DELAY + and ends at sunrise - NIGHT_BRIGHTNESS_DELAY. Color: Choose one of 25 colors for the LEDs. Colorchange: Change the color in intervals. Do not change (off), every 5 minutes (five), every hour (hour), every day (day). @@ -217,6 +222,7 @@ Configuration.h - Software settings: #define AUTO_MODECHANGE_TIME Time in seconds to wait between switching from time to temperature. #define FEED_SPEED Feed delay in milliseconds. 120 is a good start. #define SUNSET_SUNRISE_SPEED Milliseconds delay between sunrise screen -> sunrise time and sunset screen -> sunset time +#define NIGHT_BRIGHTNESS_DELAY Delay for brightness adjustment (nighttime brightness or daytime brightness) #define EVENT_TIME Time in seconds to wait between showing events. Comment to turn off events. #define ALARM_LED_COLOR Color of the alarm LED. If not defined the display color will be used. The possible colors are: @@ -236,10 +242,11 @@ Configuration.h - Software settings: #define SHOW_MODE_SUNRISE_SUNSET Show sunrise and sunset times. #define SHOW_MODE_TEST Show tests. -#define WEATHER Enable MeteoWeather usage to display weather information from the internet. -#define LATITUDE Your location latitude for MeteoWeather API. -#define LONGITUDE Your location longitude for MeteoWeather API. -#define TIMZONE Your location timezone for MeteoWeather API. +#define WEATHER Show weather (with meteoweather API) + +#define LATITUDE Latitude for weather location. +#define LONGITUDE Longitude for weather location. +#define TIMEZONE Timezone for weather location. #define TIMEZONE_* The time zone in which the clock is located. Important for the UTC offset and the summer/winter time change. @@ -415,7 +422,8 @@ hb=0 Hourly beep on [1] or off [0] ti=0 Timer in minutes mc=0 Modechange on [1] or off [0] ab=1 ABC on [1] or off [0] -br=50 Brightness in percent +br_day=50 Brightness during day in percent +br_night=50 Brightness during night in percent co=14 Number of the LEDs color. See Colors.h cc=0 Number of colorchange. See Colors.h tr=1 Number of transition. See Modes.h @@ -446,6 +454,11 @@ mode=0 Set clock to mode=0 (time), mode=1 (am/pm), ****************************************************************************** Changelog: ****************************************************************************** + +20241105: +Introduced night brightness level. The night brightness level is applied if sunrise/sunset times are available via weather API. +NIGHT_BRIGHTNESS_DELAY is subtracted from sunrise time and added to sunset time for switching between brightness values. + 20240908: Switch to MeteoWeather API for weather and sunrise/sunset information (API Key no longer required, regestration for API no longer needed). Beatification of debug output and webcontrol page for sunrise/sunset. diff --git a/Renderer.cpp b/src/Renderer.cpp similarity index 99% rename from Renderer.cpp rename to src/Renderer.cpp index ba40126..5aa7d30 100644 --- a/Renderer.cpp +++ b/src/Renderer.cpp @@ -1475,3 +1475,9 @@ void Renderer::setAllScreenBuffer(uint16_t matrix[]) { for (uint8_t i = 0; i <= 9; i++) matrix[i] = 0b1111111111111111; } + +void Renderer::setLoveSign(uint16_t matrix[]) +{ + matrix[0] = 0b0001001111000000; + matrix[4] = 0b0000111000000000; +} diff --git a/Renderer.h b/src/Renderer.h similarity index 97% rename from Renderer.h rename to src/Renderer.h index dc960e2..92a607b 100644 --- a/Renderer.h +++ b/src/Renderer.h @@ -35,6 +35,7 @@ class Renderer { void unsetPixelInScreenBuffer(uint8_t x, uint8_t y, uint16_t matrix[]); void clearScreenBuffer(uint16_t matrix[]); void setAllScreenBuffer(uint16_t matrix[]); + void setLoveSign(uint16_t matrix[]); private: boolean isNumber(char symbol); diff --git a/Settings.cpp b/src/Settings.cpp similarity index 90% rename from Settings.cpp rename to src/Settings.cpp index 6f83061..6b0da56 100644 --- a/Settings.cpp +++ b/src/Settings.cpp @@ -16,7 +16,8 @@ void Settings::resetToDefault() { mySettings.magicNumber = SETTINGS_MAGIC_NUMBER; mySettings.version = SETTINGS_VERSION; mySettings.useAbc = false; - mySettings.brightness = 50; + mySettings.brightness_during_daytime = 50; + mySettings.brightness_during_nighttime = 20; mySettings.color = WHITE; mySettings.colorChange = COLORCHANGE_NO; mySettings.transition = TRANSITION_FADE; diff --git a/Settings.h b/src/Settings.h similarity index 90% rename from Settings.h rename to src/Settings.h index 1dfdb5b..b422cfd 100644 --- a/Settings.h +++ b/src/Settings.h @@ -13,7 +13,7 @@ #include "Modes.h" #define SETTINGS_MAGIC_NUMBER 0x2A -#define SETTINGS_VERSION 25 +#define SETTINGS_VERSION 26 class Settings { public: @@ -24,7 +24,8 @@ class Settings { uint8_t magicNumber; uint8_t version; boolean useAbc; - int16_t brightness; + int16_t brightness_during_daytime; + int16_t brightness_during_nighttime; uint8_t color; uint8_t colorChange; uint8_t transition; diff --git a/Syslog.cpp b/src/Syslog.cpp similarity index 100% rename from Syslog.cpp rename to src/Syslog.cpp diff --git a/Syslog.h b/src/Syslog.h similarity index 100% rename from Syslog.h rename to src/Syslog.h diff --git a/Timezone.cpp b/src/Timezone.cpp similarity index 100% rename from Timezone.cpp rename to src/Timezone.cpp diff --git a/Timezone.h b/src/Timezone.h similarity index 100% rename from Timezone.h rename to src/Timezone.h diff --git a/Timezones.h b/src/Timezones.h similarity index 100% rename from Timezones.h rename to src/Timezones.h diff --git a/WiFiManager.cpp b/src/WiFiManager.cpp similarity index 96% rename from WiFiManager.cpp rename to src/WiFiManager.cpp index 5c4ce6b..826c6b1 100644 --- a/WiFiManager.cpp +++ b/src/WiFiManager.cpp @@ -1,846 +1,846 @@ -/************************************************************** - WiFiManager is a library for the ESP8266/Arduino platform - (https://github.com/esp8266/Arduino) to enable easy - configuration and reconfiguration of WiFi credentials using a Captive Portal - inspired by: - http://www.esp8266.com/viewtopic.php?f=29&t=2520 - https://github.com/chriscook8/esp-arduino-apboot - https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced - Built by AlexT https://github.com/tzapu - Licensed under MIT license - **************************************************************/ - -#include "WiFiManager.h" - -WiFiManagerParameter::WiFiManagerParameter(const char *custom) { - _id = NULL; - _placeholder = NULL; - _length = 0; - _value = NULL; - - _customHTML = custom; -} - -WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length) { - init(id, placeholder, defaultValue, length, ""); -} - -WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { - init(id, placeholder, defaultValue, length, custom); -} - -void WiFiManagerParameter::init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { - _id = id; - _placeholder = placeholder; - _length = length; - _value = new char[length + 1]; - for (int i = 0; i < length + 1; i++) { - _value[i] = 0; - } - if (defaultValue != NULL) { - strncpy(_value, defaultValue, length); - } - - _customHTML = custom; -} - -WiFiManagerParameter::~WiFiManagerParameter() { - if (_value != NULL) { - delete[] _value; - } -} - -const char* WiFiManagerParameter::getValue() { - return _value; -} -const char* WiFiManagerParameter::getID() { - return _id; -} -const char* WiFiManagerParameter::getPlaceholder() { - return _placeholder; -} -int WiFiManagerParameter::getValueLength() { - return _length; -} -const char* WiFiManagerParameter::getCustomHTML() { - return _customHTML; -} - - -WiFiManager::WiFiManager() { - _max_params = WIFI_MANAGER_MAX_PARAMS; - _params = (WiFiManagerParameter**)malloc(_max_params * sizeof(WiFiManagerParameter*)); -} - -WiFiManager::~WiFiManager() -{ - if (_params != NULL) - { - DEBUG_WM(F("freeing allocated params!")); - free(_params); - } -} - -bool WiFiManager::addParameter(WiFiManagerParameter *p) { - if(_paramsCount + 1 > _max_params) - { - // rezise the params array - _max_params += WIFI_MANAGER_MAX_PARAMS; - DEBUG_WM(F("Increasing _max_params to:")); - DEBUG_WM(_max_params); - WiFiManagerParameter** new_params = (WiFiManagerParameter**)realloc(_params, _max_params * sizeof(WiFiManagerParameter*)); - if (new_params != NULL) { - _params = new_params; - } else { - DEBUG_WM(F("ERROR: failed to realloc params, size not increased!")); - return false; - } - } - - _params[_paramsCount] = p; - _paramsCount++; - DEBUG_WM(F("Adding parameter")); - DEBUG_WM(p->getID()); - return true; -} - -void WiFiManager::setupConfigPortal() { - dnsServer.reset(new DNSServer()); - server.reset(new ESP8266WebServer(80)); - - DEBUG_WM(F("")); - _configPortalStart = millis(); - - DEBUG_WM(F("Configuring access point... ")); - DEBUG_WM(_apName); - if (_apPassword != NULL) { - if (strlen(_apPassword) < 8 || strlen(_apPassword) > 63) { - // fail passphrase to short or long! - DEBUG_WM(F("Invalid AccessPoint password. Ignoring")); - _apPassword = NULL; - } - DEBUG_WM(_apPassword); - } - - //optional soft ip config - if (_ap_static_ip) { - DEBUG_WM(F("Custom AP IP/GW/Subnet")); - WiFi.softAPConfig(_ap_static_ip, _ap_static_gw, _ap_static_sn); - } - - if (_apPassword != NULL) { - WiFi.softAP(_apName, _apPassword);//password option - } else { - WiFi.softAP(_apName); - } - - delay(500); // Without delay I've seen the IP address blank - DEBUG_WM(F("AP IP address: ")); - DEBUG_WM(WiFi.softAPIP()); - - /* Setup the DNS server redirecting all the domains to the apIP */ - dnsServer->setErrorReplyCode(DNSReplyCode::NoError); - dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); - - /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */ - server->on(String(F("/")).c_str(), std::bind(&WiFiManager::handleRoot, this)); - server->on(String(F("/wifi")).c_str(), std::bind(&WiFiManager::handleWifi, this, true)); - server->on(String(F("/0wifi")).c_str(), std::bind(&WiFiManager::handleWifi, this, false)); - server->on(String(F("/wifisave")).c_str(), std::bind(&WiFiManager::handleWifiSave, this)); - server->on(String(F("/i")).c_str(), std::bind(&WiFiManager::handleInfo, this)); - server->on(String(F("/r")).c_str(), std::bind(&WiFiManager::handleReset, this)); - //server->on("/generate_204", std::bind(&WiFiManager::handle204, this)); //Android/Chrome OS captive portal check. - server->on(String(F("/fwlink")).c_str(), std::bind(&WiFiManager::handleRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. - server->onNotFound (std::bind(&WiFiManager::handleNotFound, this)); - server->begin(); // Web server start - DEBUG_WM(F("HTTP server started")); -} - -boolean WiFiManager::autoConnect() { - String ssid = "ESP" + String(ESP.getChipId()); - return autoConnect(ssid.c_str(), NULL); -} - -boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { - DEBUG_WM(F("")); - DEBUG_WM(F("AutoConnect")); - - // read eeprom for ssid and pass - //String ssid = getSSID(); - //String pass = getPassword(); - - // attempt to connect; should it fail, fall back to AP - WiFi.mode(WIFI_STA); - - if (connectWifi("", "") == WL_CONNECTED) { - DEBUG_WM(F("IP Address:")); - DEBUG_WM(WiFi.localIP()); - //connected - return true; - } - - return startConfigPortal(apName, apPassword); -} - -boolean WiFiManager::configPortalHasTimeout(){ - if(_configPortalTimeout == 0 || wifi_softap_get_station_num() > 0){ - _configPortalStart = millis(); // kludge, bump configportal start time to skew timeouts - return false; - } - return (millis() > _configPortalStart + _configPortalTimeout); -} - -boolean WiFiManager::startConfigPortal() { - String ssid = "ESP" + String(ESP.getChipId()); - return startConfigPortal(ssid.c_str(), NULL); -} - -boolean WiFiManager::startConfigPortal(char const *apName, char const *apPassword) { - - if(!WiFi.isConnected()){ - WiFi.persistent(false); - // disconnect sta, start ap - WiFi.disconnect(); // this alone is not enough to stop the autoconnecter - WiFi.mode(WIFI_AP); - WiFi.persistent(true); - } - else { - //setup AP - WiFi.mode(WIFI_AP_STA); - DEBUG_WM(F("SET AP STA")); - } - - - _apName = apName; - _apPassword = apPassword; - - //notify we entered AP mode - if ( _apcallback != NULL) { - _apcallback(this); - } - - connect = false; - setupConfigPortal(); - - while(1){ - - // check if timeout - if(configPortalHasTimeout()) break; - - //DNS - dnsServer->processNextRequest(); - //HTTP - server->handleClient(); - - if (connect) { - delay(1000); - connect = false; - - // if saving with no ssid filled in, reconnect to ssid - // will not exit cp - if(_ssid == ""){ - DEBUG_WM(F("No ssid, skipping wifi")); - } - else{ - DEBUG_WM(F("Connecting to new AP")); - if (connectWifi(_ssid, _pass) != WL_CONNECTED) { - delay(2000); - // using user-provided _ssid, _pass in place of system-stored ssid and pass - DEBUG_WM(F("Failed to connect.")); - } - else { - //connected - WiFi.mode(WIFI_STA); - //notify that configuration has changed and any optional parameters should be saved - if ( _savecallback != NULL) { - //todo: check if any custom parameters actually exist, and check if they really changed maybe - _savecallback(); - } - break; - } - } - if (_shouldBreakAfterConfig) { - //flag set to exit after config after trying to connect - //notify that configuration has changed and any optional parameters should be saved - if ( _savecallback != NULL) { - //todo: check if any custom parameters actually exist, and check if they really changed maybe - _savecallback(); - } - WiFi.mode(WIFI_STA); // turn off ap - // reconnect to ssid - // int res = WiFi.begin(); - // attempt connect for 10 seconds - DEBUG_WM(F("Waiting for sta (10 secs) .......")); - for(size_t i = 0 ; i<100;i++){ - if(WiFi.status() == WL_CONNECTED) break; - DEBUG_WM("."); - // Serial.println(WiFi.status()); - delay(100); - } - delay(1000); - break; - } - } - yield(); - } - - server.reset(); - dnsServer.reset(); - - return WiFi.status() == WL_CONNECTED; -} - - -int WiFiManager::connectWifi(String ssid, String pass) { - DEBUG_WM(F("Connecting as wifi client...")); - - // check if we've got static_ip settings, if we do, use those. - if (_sta_static_ip) { - DEBUG_WM(F("Custom STA IP/GW/Subnet")); - WiFi.config(_sta_static_ip, _sta_static_gw, _sta_static_sn); - DEBUG_WM(WiFi.localIP()); - } - //fix for auto connect racing issue - if (WiFi.status() == WL_CONNECTED && (WiFi.SSID() == ssid)) { - DEBUG_WM(F("Already connected. Bailing out.")); - return WL_CONNECTED; - } - - DEBUG_WM(F("Status:")); - DEBUG_WM(WiFi.status()); - - wl_status_t res; - //check if we have ssid and pass and force those, if not, try with last saved values - if (ssid != "") { - //trying to fix connection in progress hanging - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - res = WiFi.begin(ssid.c_str(), pass.c_str(),0,NULL,true); - if(res != WL_CONNECTED){ - DEBUG_WM(F("[ERROR] WiFi.begin res:")); - DEBUG_WM(res); - } - } else { - if (WiFi.SSID() != "") { - DEBUG_WM(F("Using last saved values, should be faster")); - //trying to fix connection in progress hanging - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - res = WiFi.begin(); - } else { - DEBUG_WM(F("No saved credentials")); - } - } - - int connRes = waitForConnectResult(); - DEBUG_WM ("Connection result: "); - DEBUG_WM ( connRes ); - //not connected, WPS enabled, no pass - first attempt - #ifdef NO_EXTRA_4K_HEAP - if (_tryWPS && connRes != WL_CONNECTED && pass == "") { - startWPS(); - //should be connected at the end of WPS - connRes = waitForConnectResult(); - } - #endif - return connRes; -} - -uint8_t WiFiManager::waitForConnectResult() { - if (_connectTimeout == 0) { - return WiFi.waitForConnectResult(); - } else { - DEBUG_WM (F("Waiting for connection result with time out")); - unsigned long start = millis(); - boolean keepConnecting = true; - uint8_t status; - while (keepConnecting) { - status = WiFi.status(); - if (millis() > start + _connectTimeout) { - keepConnecting = false; - DEBUG_WM (F("Connection timed out")); - } - if (status == WL_CONNECTED) { - keepConnecting = false; - } - delay(100); - } - return status; - } -} - -void WiFiManager::startWPS() { - DEBUG_WM(F("START WPS")); - WiFi.beginWPSConfig(); - DEBUG_WM(F("END WPS")); -} -/* - String WiFiManager::getSSID() { - if (_ssid == "") { - DEBUG_WM(F("Reading SSID")); - _ssid = WiFi.SSID(); - DEBUG_WM(F("SSID: ")); - DEBUG_WM(_ssid); - } - return _ssid; - } - String WiFiManager::getPassword() { - if (_pass == "") { - DEBUG_WM(F("Reading Password")); - _pass = WiFi.psk(); - DEBUG_WM("Password: " + _pass); - //DEBUG_WM(_pass); - } - return _pass; - } -*/ -String WiFiManager::getConfigPortalSSID() { - return _apName; -} - -void WiFiManager::resetSettings() { - DEBUG_WM(F("settings invalidated")); - DEBUG_WM(F("THIS MAY CAUSE AP NOT TO START UP PROPERLY. YOU NEED TO COMMENT IT OUT AFTER ERASING THE DATA.")); - WiFi.disconnect(true); - //delay(200); -} -void WiFiManager::setTimeout(unsigned long seconds) { - setConfigPortalTimeout(seconds); -} - -void WiFiManager::setConfigPortalTimeout(unsigned long seconds) { - _configPortalTimeout = seconds * 1000; -} - -void WiFiManager::setConnectTimeout(unsigned long seconds) { - _connectTimeout = seconds * 1000; -} - -void WiFiManager::setDebugOutput(boolean debug) { - _debug = debug; -} - -void WiFiManager::setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) { - _ap_static_ip = ip; - _ap_static_gw = gw; - _ap_static_sn = sn; -} - -void WiFiManager::setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) { - _sta_static_ip = ip; - _sta_static_gw = gw; - _sta_static_sn = sn; -} - -void WiFiManager::setMinimumSignalQuality(int quality) { - _minimumQuality = quality; -} - -void WiFiManager::setBreakAfterConfig(boolean shouldBreak) { - _shouldBreakAfterConfig = shouldBreak; -} - -/** Handle root or redirect to captive portal */ -void WiFiManager::handleRoot() { - DEBUG_WM(F("Handle root")); - if (captivePortal()) { // If caprive portal redirect instead of displaying the page. - return; - } - - String page = FPSTR(HTTP_HEADER); - page.replace("{v}", "Options"); - page += FPSTR(HTTP_SCRIPT); - page += FPSTR(HTTP_STYLE); - page += _customHeadElement; - page += FPSTR(HTTP_HEADER_END); - page += String(F("

")); - page += _apName; - page += String(F("

")); - page += String(F("

WiFiManager

")); - page += FPSTR(HTTP_PORTAL_OPTIONS); - page += FPSTR(HTTP_END); - - server->sendHeader("Content-Length", String(page.length())); - server->send(200, "text/html", page); - -} - -/** Wifi config page handler */ -void WiFiManager::handleWifi(boolean scan) { - - String page = FPSTR(HTTP_HEADER); - page.replace("{v}", "Config ESP"); - page += FPSTR(HTTP_SCRIPT); - page += FPSTR(HTTP_STYLE); - page += _customHeadElement; - page += FPSTR(HTTP_HEADER_END); - - if (scan) { - int n = WiFi.scanNetworks(); - DEBUG_WM(F("Scan done")); - if (n == 0) { - DEBUG_WM(F("No networks found")); - page += F("No networks found. Refresh to scan again."); - } else { - - //sort networks - int indices[n]; - for (int i = 0; i < n; i++) { - indices[i] = i; - } - - // RSSI SORT - - // old sort - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { - std::swap(indices[i], indices[j]); - } - } - } - - /*std::sort(indices, indices + n, [](const int & a, const int & b) -> bool - { - return WiFi.RSSI(a) > WiFi.RSSI(b); - });*/ - - // remove duplicates ( must be RSSI sorted ) - if (_removeDuplicateAPs) { - String cssid; - for (int i = 0; i < n; i++) { - if (indices[i] == -1) continue; - cssid = WiFi.SSID(indices[i]); - for (int j = i + 1; j < n; j++) { - if (cssid == WiFi.SSID(indices[j])) { - DEBUG_WM("DUP AP: " + WiFi.SSID(indices[j])); - indices[j] = -1; // set dup aps to index -1 - } - } - } - } - - //display networks in page - for (int i = 0; i < n; i++) { - if (indices[i] == -1) continue; // skip dups - DEBUG_WM(WiFi.SSID(indices[i])); - DEBUG_WM(WiFi.RSSI(indices[i])); - int quality = getRSSIasQuality(WiFi.RSSI(indices[i])); - - if (_minimumQuality == -1 || _minimumQuality < quality) { - String item = FPSTR(HTTP_ITEM); - String rssiQ; - rssiQ += quality; - item.replace("{v}", WiFi.SSID(indices[i])); - item.replace("{r}", rssiQ); - if (WiFi.encryptionType(indices[i]) != ENC_TYPE_NONE) { - item.replace("{i}", "l"); - } else { - item.replace("{i}", ""); - } - //DEBUG_WM(item); - page += item; - delay(0); - } else { - DEBUG_WM(F("Skipping due to quality")); - } - - } - page += "
"; - } - } - - page += FPSTR(HTTP_FORM_START); - char parLength[5]; - // add the extra parameters to the form - for (int i = 0; i < _paramsCount; i++) { - if (_params[i] == NULL) { - break; - } - - String pitem = FPSTR(HTTP_FORM_PARAM); - if (_params[i]->getID() != NULL) { - pitem.replace("{i}", _params[i]->getID()); - pitem.replace("{n}", _params[i]->getID()); - pitem.replace("{p}", _params[i]->getPlaceholder()); - snprintf(parLength, 5, "%d", _params[i]->getValueLength()); - pitem.replace("{l}", parLength); - pitem.replace("{v}", _params[i]->getValue()); - pitem.replace("{c}", _params[i]->getCustomHTML()); - } else { - pitem = _params[i]->getCustomHTML(); - } - - page += pitem; - } - if (_params[0] != NULL) { - page += "
"; - } - - if (_sta_static_ip) { - - String item = FPSTR(HTTP_FORM_PARAM); - item.replace("{i}", "ip"); - item.replace("{n}", "ip"); - item.replace("{p}", "Static IP"); - item.replace("{l}", "15"); - item.replace("{v}", _sta_static_ip.toString()); - - page += item; - - item = FPSTR(HTTP_FORM_PARAM); - item.replace("{i}", "gw"); - item.replace("{n}", "gw"); - item.replace("{p}", "Static Gateway"); - item.replace("{l}", "15"); - item.replace("{v}", _sta_static_gw.toString()); - - page += item; - - item = FPSTR(HTTP_FORM_PARAM); - item.replace("{i}", "sn"); - item.replace("{n}", "sn"); - item.replace("{p}", "Subnet"); - item.replace("{l}", "15"); - item.replace("{v}", _sta_static_sn.toString()); - - page += item; - - page += "
"; - } - - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_SCAN_LINK); - - page += FPSTR(HTTP_END); - - server->sendHeader("Content-Length", String(page.length())); - server->send(200, "text/html", page); - - - DEBUG_WM(F("Sent config page")); -} - -/** Handle the WLAN save form and redirect to WLAN config page again */ -void WiFiManager::handleWifiSave() { - DEBUG_WM(F("WiFi save")); - - //SAVE/connect here - _ssid = server->arg("s").c_str(); - _pass = server->arg("p").c_str(); - - //parameters - for (int i = 0; i < _paramsCount; i++) { - if (_params[i] == NULL) { - break; - } - //read parameter - String value = server->arg(_params[i]->getID()).c_str(); - //store it in array - value.toCharArray(_params[i]->_value, _params[i]->_length + 1); - DEBUG_WM(F("Parameter")); - DEBUG_WM(_params[i]->getID()); - DEBUG_WM(value); - } - - if (server->arg("ip") != "") { - DEBUG_WM(F("static ip")); - DEBUG_WM(server->arg("ip")); - //_sta_static_ip.fromString(server->arg("ip")); - String ip = server->arg("ip"); - optionalIPFromString(&_sta_static_ip, ip.c_str()); - } - if (server->arg("gw") != "") { - DEBUG_WM(F("static gateway")); - DEBUG_WM(server->arg("gw")); - String gw = server->arg("gw"); - optionalIPFromString(&_sta_static_gw, gw.c_str()); - } - if (server->arg("sn") != "") { - DEBUG_WM(F("static netmask")); - DEBUG_WM(server->arg("sn")); - String sn = server->arg("sn"); - optionalIPFromString(&_sta_static_sn, sn.c_str()); - } - - String page = FPSTR(HTTP_HEADER); - page.replace("{v}", "Credentials Saved"); - page += FPSTR(HTTP_SCRIPT); - page += FPSTR(HTTP_STYLE); - page += _customHeadElement; - page += FPSTR(HTTP_HEADER_END); - page += FPSTR(HTTP_SAVED); - page += FPSTR(HTTP_END); - - server->sendHeader("Content-Length", String(page.length())); - server->send(200, "text/html", page); - - DEBUG_WM(F("Sent wifi save page")); - - connect = true; //signal ready to connect/reset -} - -/** Handle the info page */ -void WiFiManager::handleInfo() { - DEBUG_WM(F("Info")); - - String page = FPSTR(HTTP_HEADER); - page.replace("{v}", "Info"); - page += FPSTR(HTTP_SCRIPT); - page += FPSTR(HTTP_STYLE); - page += _customHeadElement; - page += FPSTR(HTTP_HEADER_END); - page += F("
"); - page += F("
Chip ID
"); - page += ESP.getChipId(); - page += F("
"); - page += F("
Flash Chip ID
"); - page += ESP.getFlashChipId(); - page += F("
"); - page += F("
IDE Flash Size
"); - page += ESP.getFlashChipSize(); - page += F(" bytes
"); - page += F("
Real Flash Size
"); - page += ESP.getFlashChipRealSize(); - page += F(" bytes
"); - page += F("
Soft AP IP
"); - page += WiFi.softAPIP().toString(); - page += F("
"); - page += F("
Soft AP MAC
"); - page += WiFi.softAPmacAddress(); - page += F("
"); - page += F("
Station MAC
"); - page += WiFi.macAddress(); - page += F("
"); - page += F("
"); - page += FPSTR(HTTP_END); - - server->sendHeader("Content-Length", String(page.length())); - server->send(200, "text/html", page); - - DEBUG_WM(F("Sent info page")); -} - -/** Handle the reset page */ -void WiFiManager::handleReset() { - DEBUG_WM(F("Reset")); - - String page = FPSTR(HTTP_HEADER); - page.replace("{v}", "Info"); - page += FPSTR(HTTP_SCRIPT); - page += FPSTR(HTTP_STYLE); - page += _customHeadElement; - page += FPSTR(HTTP_HEADER_END); - page += F("Module will reset in a few seconds."); - page += FPSTR(HTTP_END); - - server->sendHeader("Content-Length", String(page.length())); - server->send(200, "text/html", page); - - DEBUG_WM(F("Sent reset page")); - delay(5000); - ESP.reset(); - delay(2000); -} - -void WiFiManager::handleNotFound() { - if (captivePortal()) { // If captive portal redirect instead of displaying the error page. - return; - } - String message = "File Not Found\n\n"; - message += "URI: "; - message += server->uri(); - message += "\nMethod: "; - message += ( server->method() == HTTP_GET ) ? "GET" : "POST"; - message += "\nArguments: "; - message += server->args(); - message += "\n"; - - for ( uint8_t i = 0; i < server->args(); i++ ) { - message += " " + server->argName ( i ) + ": " + server->arg ( i ) + "\n"; - } - server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - server->sendHeader("Pragma", "no-cache"); - server->sendHeader("Expires", "-1"); - server->sendHeader("Content-Length", String(message.length())); - server->send ( 404, "text/plain", message ); -} - - -/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ -boolean WiFiManager::captivePortal() { - if (!isIp(server->hostHeader()) ) { - DEBUG_WM(F("Request redirected to captive portal")); - server->sendHeader("Location", String("http://") + toStringIp(server->client().localIP()), true); - server->send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. - server->client().stop(); // Stop is needed because we sent no content length - return true; - } - return false; -} - -//start up config portal callback -void WiFiManager::setAPCallback( void (*func)(WiFiManager* myWiFiManager) ) { - _apcallback = func; -} - -//start up save config callback -void WiFiManager::setSaveConfigCallback( void (*func)(void) ) { - _savecallback = func; -} - -//sets a custom element to add to head, like a new style tag -void WiFiManager::setCustomHeadElement(const char* element) { - _customHeadElement = element; -} - -//if this is true, remove duplicated Access Points - defaut true -void WiFiManager::setRemoveDuplicateAPs(boolean removeDuplicates) { - _removeDuplicateAPs = removeDuplicates; -} - - - -template -void WiFiManager::DEBUG_WM(Generic text) { - if (_debug) { - Serial.print("*WM: "); - Serial.println(text); - } -} - -int WiFiManager::getRSSIasQuality(int RSSI) { - int quality = 0; - - if (RSSI <= -100) { - quality = 0; - } else if (RSSI >= -50) { - quality = 100; - } else { - quality = 2 * (RSSI + 100); - } - return quality; -} - -/** Is this an IP? */ -boolean WiFiManager::isIp(String str) { - for (size_t i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c != '.' && (c < '0' || c > '9')) { - return false; - } - } - return true; -} - -/** IP to String? */ -String WiFiManager::toStringIp(IPAddress ip) { - String res = ""; - for (int i = 0; i < 3; i++) { - res += String((ip >> (8 * i)) & 0xFF) + "."; - } - res += String(((ip >> 8 * 3)) & 0xFF); - return res; -} +/************************************************************** + WiFiManager is a library for the ESP8266/Arduino platform + (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal + inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced + Built by AlexT https://github.com/tzapu + Licensed under MIT license + **************************************************************/ + +#include "WiFiManager.h" + +WiFiManagerParameter::WiFiManagerParameter(const char *custom) { + _id = NULL; + _placeholder = NULL; + _length = 0; + _value = NULL; + + _customHTML = custom; +} + +WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length) { + init(id, placeholder, defaultValue, length, ""); +} + +WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { + init(id, placeholder, defaultValue, length, custom); +} + +void WiFiManagerParameter::init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom) { + _id = id; + _placeholder = placeholder; + _length = length; + _value = new char[length + 1]; + for (int i = 0; i < length + 1; i++) { + _value[i] = 0; + } + if (defaultValue != NULL) { + strncpy(_value, defaultValue, length); + } + + _customHTML = custom; +} + +WiFiManagerParameter::~WiFiManagerParameter() { + if (_value != NULL) { + delete[] _value; + } +} + +const char* WiFiManagerParameter::getValue() { + return _value; +} +const char* WiFiManagerParameter::getID() { + return _id; +} +const char* WiFiManagerParameter::getPlaceholder() { + return _placeholder; +} +int WiFiManagerParameter::getValueLength() { + return _length; +} +const char* WiFiManagerParameter::getCustomHTML() { + return _customHTML; +} + + +WiFiManager::WiFiManager() { + _max_params = WIFI_MANAGER_MAX_PARAMS; + _params = (WiFiManagerParameter**)malloc(_max_params * sizeof(WiFiManagerParameter*)); +} + +WiFiManager::~WiFiManager() +{ + if (_params != NULL) + { + DEBUG_WM(F("freeing allocated params!")); + free(_params); + } +} + +bool WiFiManager::addParameter(WiFiManagerParameter *p) { + if(_paramsCount + 1 > _max_params) + { + // rezise the params array + _max_params += WIFI_MANAGER_MAX_PARAMS; + DEBUG_WM(F("Increasing _max_params to:")); + DEBUG_WM(_max_params); + WiFiManagerParameter** new_params = (WiFiManagerParameter**)realloc(_params, _max_params * sizeof(WiFiManagerParameter*)); + if (new_params != NULL) { + _params = new_params; + } else { + DEBUG_WM(F("ERROR: failed to realloc params, size not increased!")); + return false; + } + } + + _params[_paramsCount] = p; + _paramsCount++; + DEBUG_WM(F("Adding parameter")); + DEBUG_WM(p->getID()); + return true; +} + +void WiFiManager::setupConfigPortal() { + dnsServer.reset(new DNSServer()); + server.reset(new ESP8266WebServer(80)); + + DEBUG_WM(F("")); + _configPortalStart = millis(); + + DEBUG_WM(F("Configuring access point... ")); + DEBUG_WM(_apName); + if (_apPassword != NULL) { + if (strlen(_apPassword) < 8 || strlen(_apPassword) > 63) { + // fail passphrase to short or long! + DEBUG_WM(F("Invalid AccessPoint password. Ignoring")); + _apPassword = NULL; + } + DEBUG_WM(_apPassword); + } + + //optional soft ip config + if (_ap_static_ip) { + DEBUG_WM(F("Custom AP IP/GW/Subnet")); + WiFi.softAPConfig(_ap_static_ip, _ap_static_gw, _ap_static_sn); + } + + if (_apPassword != NULL) { + WiFi.softAP(_apName, _apPassword);//password option + } else { + WiFi.softAP(_apName); + } + + delay(500); // Without delay I've seen the IP address blank + DEBUG_WM(F("AP IP address: ")); + DEBUG_WM(WiFi.softAPIP()); + + /* Setup the DNS server redirecting all the domains to the apIP */ + dnsServer->setErrorReplyCode(DNSReplyCode::NoError); + dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); + + /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */ + server->on(String(F("/")).c_str(), std::bind(&WiFiManager::handleRoot, this)); + server->on(String(F("/wifi")).c_str(), std::bind(&WiFiManager::handleWifi, this, true)); + server->on(String(F("/0wifi")).c_str(), std::bind(&WiFiManager::handleWifi, this, false)); + server->on(String(F("/wifisave")).c_str(), std::bind(&WiFiManager::handleWifiSave, this)); + server->on(String(F("/i")).c_str(), std::bind(&WiFiManager::handleInfo, this)); + server->on(String(F("/r")).c_str(), std::bind(&WiFiManager::handleReset, this)); + //server->on("/generate_204", std::bind(&WiFiManager::handle204, this)); //Android/Chrome OS captive portal check. + server->on(String(F("/fwlink")).c_str(), std::bind(&WiFiManager::handleRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. + server->onNotFound (std::bind(&WiFiManager::handleNotFound, this)); + server->begin(); // Web server start + DEBUG_WM(F("HTTP server started")); +} + +boolean WiFiManager::autoConnect() { + String ssid = "ESP" + String(ESP.getChipId()); + return autoConnect(ssid.c_str(), NULL); +} + +boolean WiFiManager::autoConnect(char const *apName, char const *apPassword) { + DEBUG_WM(F("")); + DEBUG_WM(F("AutoConnect")); + + // read eeprom for ssid and pass + //String ssid = getSSID(); + //String pass = getPassword(); + + // attempt to connect; should it fail, fall back to AP + WiFi.mode(WIFI_STA); + + if (connectWifi("", "") == WL_CONNECTED) { + DEBUG_WM(F("IP Address:")); + DEBUG_WM(WiFi.localIP()); + //connected + return true; + } + + return startConfigPortal(apName, apPassword); +} + +boolean WiFiManager::configPortalHasTimeout(){ + if(_configPortalTimeout == 0 || wifi_softap_get_station_num() > 0){ + _configPortalStart = millis(); // kludge, bump configportal start time to skew timeouts + return false; + } + return (millis() > _configPortalStart + _configPortalTimeout); +} + +boolean WiFiManager::startConfigPortal() { + String ssid = "ESP" + String(ESP.getChipId()); + return startConfigPortal(ssid.c_str(), NULL); +} + +boolean WiFiManager::startConfigPortal(char const *apName, char const *apPassword) { + + if(!WiFi.isConnected()){ + WiFi.persistent(false); + // disconnect sta, start ap + WiFi.disconnect(); // this alone is not enough to stop the autoconnecter + WiFi.mode(WIFI_AP); + WiFi.persistent(true); + } + else { + //setup AP + WiFi.mode(WIFI_AP_STA); + DEBUG_WM(F("SET AP STA")); + } + + + _apName = apName; + _apPassword = apPassword; + + //notify we entered AP mode + if ( _apcallback != NULL) { + _apcallback(this); + } + + connect = false; + setupConfigPortal(); + + while(1){ + + // check if timeout + if(configPortalHasTimeout()) break; + + //DNS + dnsServer->processNextRequest(); + //HTTP + server->handleClient(); + + if (connect) { + delay(1000); + connect = false; + + // if saving with no ssid filled in, reconnect to ssid + // will not exit cp + if(_ssid == ""){ + DEBUG_WM(F("No ssid, skipping wifi")); + } + else{ + DEBUG_WM(F("Connecting to new AP")); + if (connectWifi(_ssid, _pass) != WL_CONNECTED) { + delay(2000); + // using user-provided _ssid, _pass in place of system-stored ssid and pass + DEBUG_WM(F("Failed to connect.")); + } + else { + //connected + WiFi.mode(WIFI_STA); + //notify that configuration has changed and any optional parameters should be saved + if ( _savecallback != NULL) { + //todo: check if any custom parameters actually exist, and check if they really changed maybe + _savecallback(); + } + break; + } + } + if (_shouldBreakAfterConfig) { + //flag set to exit after config after trying to connect + //notify that configuration has changed and any optional parameters should be saved + if ( _savecallback != NULL) { + //todo: check if any custom parameters actually exist, and check if they really changed maybe + _savecallback(); + } + WiFi.mode(WIFI_STA); // turn off ap + // reconnect to ssid + // int res = WiFi.begin(); + // attempt connect for 10 seconds + DEBUG_WM(F("Waiting for sta (10 secs) .......")); + for(size_t i = 0 ; i<100;i++){ + if(WiFi.status() == WL_CONNECTED) break; + DEBUG_WM("."); + // Serial.println(WiFi.status()); + delay(100); + } + delay(1000); + break; + } + } + yield(); + } + + server.reset(); + dnsServer.reset(); + + return WiFi.status() == WL_CONNECTED; +} + + +int WiFiManager::connectWifi(String ssid, String pass) { + DEBUG_WM(F("Connecting as wifi client...")); + + // check if we've got static_ip settings, if we do, use those. + if (_sta_static_ip) { + DEBUG_WM(F("Custom STA IP/GW/Subnet")); + WiFi.config(_sta_static_ip, _sta_static_gw, _sta_static_sn); + DEBUG_WM(WiFi.localIP()); + } + //fix for auto connect racing issue + if (WiFi.status() == WL_CONNECTED && (WiFi.SSID() == ssid)) { + DEBUG_WM(F("Already connected. Bailing out.")); + return WL_CONNECTED; + } + + DEBUG_WM(F("Status:")); + DEBUG_WM(WiFi.status()); + + wl_status_t res; + //check if we have ssid and pass and force those, if not, try with last saved values + if (ssid != "") { + //trying to fix connection in progress hanging + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + res = WiFi.begin(ssid.c_str(), pass.c_str(),0,NULL,true); + if(res != WL_CONNECTED){ + DEBUG_WM(F("[ERROR] WiFi.begin res:")); + DEBUG_WM(res); + } + } else { + if (WiFi.SSID() != "") { + DEBUG_WM(F("Using last saved values, should be faster")); + //trying to fix connection in progress hanging + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + res = WiFi.begin(); + } else { + DEBUG_WM(F("No saved credentials")); + } + } + + int connRes = waitForConnectResult(); + DEBUG_WM ("Connection result: "); + DEBUG_WM ( connRes ); + //not connected, WPS enabled, no pass - first attempt + #ifdef NO_EXTRA_4K_HEAP + if (_tryWPS && connRes != WL_CONNECTED && pass == "") { + startWPS(); + //should be connected at the end of WPS + connRes = waitForConnectResult(); + } + #endif + return connRes; +} + +uint8_t WiFiManager::waitForConnectResult() { + if (_connectTimeout == 0) { + return WiFi.waitForConnectResult(); + } else { + DEBUG_WM (F("Waiting for connection result with time out")); + unsigned long start = millis(); + boolean keepConnecting = true; + uint8_t status; + while (keepConnecting) { + status = WiFi.status(); + if (millis() > start + _connectTimeout) { + keepConnecting = false; + DEBUG_WM (F("Connection timed out")); + } + if (status == WL_CONNECTED) { + keepConnecting = false; + } + delay(100); + } + return status; + } +} + +void WiFiManager::startWPS() { + DEBUG_WM(F("START WPS")); + WiFi.beginWPSConfig(); + DEBUG_WM(F("END WPS")); +} +/* + String WiFiManager::getSSID() { + if (_ssid == "") { + DEBUG_WM(F("Reading SSID")); + _ssid = WiFi.SSID(); + DEBUG_WM(F("SSID: ")); + DEBUG_WM(_ssid); + } + return _ssid; + } + String WiFiManager::getPassword() { + if (_pass == "") { + DEBUG_WM(F("Reading Password")); + _pass = WiFi.psk(); + DEBUG_WM("Password: " + _pass); + //DEBUG_WM(_pass); + } + return _pass; + } +*/ +String WiFiManager::getConfigPortalSSID() { + return _apName; +} + +void WiFiManager::resetSettings() { + DEBUG_WM(F("settings invalidated")); + DEBUG_WM(F("THIS MAY CAUSE AP NOT TO START UP PROPERLY. YOU NEED TO COMMENT IT OUT AFTER ERASING THE DATA.")); + WiFi.disconnect(true); + //delay(200); +} +void WiFiManager::setTimeout(unsigned long seconds) { + setConfigPortalTimeout(seconds); +} + +void WiFiManager::setConfigPortalTimeout(unsigned long seconds) { + _configPortalTimeout = seconds * 1000; +} + +void WiFiManager::setConnectTimeout(unsigned long seconds) { + _connectTimeout = seconds * 1000; +} + +void WiFiManager::setDebugOutput(boolean debug) { + _debug = debug; +} + +void WiFiManager::setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) { + _ap_static_ip = ip; + _ap_static_gw = gw; + _ap_static_sn = sn; +} + +void WiFiManager::setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) { + _sta_static_ip = ip; + _sta_static_gw = gw; + _sta_static_sn = sn; +} + +void WiFiManager::setMinimumSignalQuality(int quality) { + _minimumQuality = quality; +} + +void WiFiManager::setBreakAfterConfig(boolean shouldBreak) { + _shouldBreakAfterConfig = shouldBreak; +} + +/** Handle root or redirect to captive portal */ +void WiFiManager::handleRoot() { + DEBUG_WM(F("Handle root")); + if (captivePortal()) { // If caprive portal redirect instead of displaying the page. + return; + } + + String page = FPSTR(HTTP_HEADER); + page.replace("{v}", "Options"); + page += FPSTR(HTTP_SCRIPT); + page += FPSTR(HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(HTTP_HEADER_END); + page += String(F("

")); + page += _apName; + page += String(F("

")); + page += String(F("

WiFiManager

")); + page += FPSTR(HTTP_PORTAL_OPTIONS); + page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); + server->send(200, "text/html", page); + +} + +/** Wifi config page handler */ +void WiFiManager::handleWifi(boolean scan) { + + String page = FPSTR(HTTP_HEADER); + page.replace("{v}", "Config ESP"); + page += FPSTR(HTTP_SCRIPT); + page += FPSTR(HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(HTTP_HEADER_END); + + if (scan) { + int n = WiFi.scanNetworks(); + DEBUG_WM(F("Scan done")); + if (n == 0) { + DEBUG_WM(F("No networks found")); + page += F("No networks found. Refresh to scan again."); + } else { + + //sort networks + int indices[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + // RSSI SORT + + // old sort + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { + std::swap(indices[i], indices[j]); + } + } + } + + /*std::sort(indices, indices + n, [](const int & a, const int & b) -> bool + { + return WiFi.RSSI(a) > WiFi.RSSI(b); + });*/ + + // remove duplicates ( must be RSSI sorted ) + if (_removeDuplicateAPs) { + String cssid; + for (int i = 0; i < n; i++) { + if (indices[i] == -1) continue; + cssid = WiFi.SSID(indices[i]); + for (int j = i + 1; j < n; j++) { + if (cssid == WiFi.SSID(indices[j])) { + DEBUG_WM("DUP AP: " + WiFi.SSID(indices[j])); + indices[j] = -1; // set dup aps to index -1 + } + } + } + } + + //display networks in page + for (int i = 0; i < n; i++) { + if (indices[i] == -1) continue; // skip dups + DEBUG_WM(WiFi.SSID(indices[i])); + DEBUG_WM(WiFi.RSSI(indices[i])); + int quality = getRSSIasQuality(WiFi.RSSI(indices[i])); + + if (_minimumQuality == -1 || _minimumQuality < quality) { + String item = FPSTR(HTTP_ITEM); + String rssiQ; + rssiQ += quality; + item.replace("{v}", WiFi.SSID(indices[i])); + item.replace("{r}", rssiQ); + if (WiFi.encryptionType(indices[i]) != ENC_TYPE_NONE) { + item.replace("{i}", "l"); + } else { + item.replace("{i}", ""); + } + //DEBUG_WM(item); + page += item; + delay(0); + } else { + DEBUG_WM(F("Skipping due to quality")); + } + + } + page += "
"; + } + } + + page += FPSTR(HTTP_FORM_START); + char parLength[5]; + // add the extra parameters to the form + for (int i = 0; i < _paramsCount; i++) { + if (_params[i] == NULL) { + break; + } + + String pitem = FPSTR(HTTP_FORM_PARAM); + if (_params[i]->getID() != NULL) { + pitem.replace("{i}", _params[i]->getID()); + pitem.replace("{n}", _params[i]->getID()); + pitem.replace("{p}", _params[i]->getPlaceholder()); + snprintf(parLength, 5, "%d", _params[i]->getValueLength()); + pitem.replace("{l}", parLength); + pitem.replace("{v}", _params[i]->getValue()); + pitem.replace("{c}", _params[i]->getCustomHTML()); + } else { + pitem = _params[i]->getCustomHTML(); + } + + page += pitem; + } + if (_params[0] != NULL) { + page += "
"; + } + + if (_sta_static_ip) { + + String item = FPSTR(HTTP_FORM_PARAM); + item.replace("{i}", "ip"); + item.replace("{n}", "ip"); + item.replace("{p}", "Static IP"); + item.replace("{l}", "15"); + item.replace("{v}", _sta_static_ip.toString()); + + page += item; + + item = FPSTR(HTTP_FORM_PARAM); + item.replace("{i}", "gw"); + item.replace("{n}", "gw"); + item.replace("{p}", "Static Gateway"); + item.replace("{l}", "15"); + item.replace("{v}", _sta_static_gw.toString()); + + page += item; + + item = FPSTR(HTTP_FORM_PARAM); + item.replace("{i}", "sn"); + item.replace("{n}", "sn"); + item.replace("{p}", "Subnet"); + item.replace("{l}", "15"); + item.replace("{v}", _sta_static_sn.toString()); + + page += item; + + page += "
"; + } + + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_SCAN_LINK); + + page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); + server->send(200, "text/html", page); + + + DEBUG_WM(F("Sent config page")); +} + +/** Handle the WLAN save form and redirect to WLAN config page again */ +void WiFiManager::handleWifiSave() { + DEBUG_WM(F("WiFi save")); + + //SAVE/connect here + _ssid = server->arg("s").c_str(); + _pass = server->arg("p").c_str(); + + //parameters + for (int i = 0; i < _paramsCount; i++) { + if (_params[i] == NULL) { + break; + } + //read parameter + String value = server->arg(_params[i]->getID()).c_str(); + //store it in array + value.toCharArray(_params[i]->_value, _params[i]->_length + 1); + DEBUG_WM(F("Parameter")); + DEBUG_WM(_params[i]->getID()); + DEBUG_WM(value); + } + + if (server->arg("ip") != "") { + DEBUG_WM(F("static ip")); + DEBUG_WM(server->arg("ip")); + //_sta_static_ip.fromString(server->arg("ip")); + String ip = server->arg("ip"); + optionalIPFromString(&_sta_static_ip, ip.c_str()); + } + if (server->arg("gw") != "") { + DEBUG_WM(F("static gateway")); + DEBUG_WM(server->arg("gw")); + String gw = server->arg("gw"); + optionalIPFromString(&_sta_static_gw, gw.c_str()); + } + if (server->arg("sn") != "") { + DEBUG_WM(F("static netmask")); + DEBUG_WM(server->arg("sn")); + String sn = server->arg("sn"); + optionalIPFromString(&_sta_static_sn, sn.c_str()); + } + + String page = FPSTR(HTTP_HEADER); + page.replace("{v}", "Credentials Saved"); + page += FPSTR(HTTP_SCRIPT); + page += FPSTR(HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(HTTP_HEADER_END); + page += FPSTR(HTTP_SAVED); + page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); + server->send(200, "text/html", page); + + DEBUG_WM(F("Sent wifi save page")); + + connect = true; //signal ready to connect/reset +} + +/** Handle the info page */ +void WiFiManager::handleInfo() { + DEBUG_WM(F("Info")); + + String page = FPSTR(HTTP_HEADER); + page.replace("{v}", "Info"); + page += FPSTR(HTTP_SCRIPT); + page += FPSTR(HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(HTTP_HEADER_END); + page += F("
"); + page += F("
Chip ID
"); + page += ESP.getChipId(); + page += F("
"); + page += F("
Flash Chip ID
"); + page += ESP.getFlashChipId(); + page += F("
"); + page += F("
IDE Flash Size
"); + page += ESP.getFlashChipSize(); + page += F(" bytes
"); + page += F("
Real Flash Size
"); + page += ESP.getFlashChipRealSize(); + page += F(" bytes
"); + page += F("
Soft AP IP
"); + page += WiFi.softAPIP().toString(); + page += F("
"); + page += F("
Soft AP MAC
"); + page += WiFi.softAPmacAddress(); + page += F("
"); + page += F("
Station MAC
"); + page += WiFi.macAddress(); + page += F("
"); + page += F("
"); + page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); + server->send(200, "text/html", page); + + DEBUG_WM(F("Sent info page")); +} + +/** Handle the reset page */ +void WiFiManager::handleReset() { + DEBUG_WM(F("Reset")); + + String page = FPSTR(HTTP_HEADER); + page.replace("{v}", "Info"); + page += FPSTR(HTTP_SCRIPT); + page += FPSTR(HTTP_STYLE); + page += _customHeadElement; + page += FPSTR(HTTP_HEADER_END); + page += F("Module will reset in a few seconds."); + page += FPSTR(HTTP_END); + + server->sendHeader("Content-Length", String(page.length())); + server->send(200, "text/html", page); + + DEBUG_WM(F("Sent reset page")); + delay(5000); + ESP.reset(); + delay(2000); +} + +void WiFiManager::handleNotFound() { + if (captivePortal()) { // If captive portal redirect instead of displaying the error page. + return; + } + String message = "File Not Found\n\n"; + message += "URI: "; + message += server->uri(); + message += "\nMethod: "; + message += ( server->method() == HTTP_GET ) ? "GET" : "POST"; + message += "\nArguments: "; + message += server->args(); + message += "\n"; + + for ( uint8_t i = 0; i < server->args(); i++ ) { + message += " " + server->argName ( i ) + ": " + server->arg ( i ) + "\n"; + } + server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server->sendHeader("Pragma", "no-cache"); + server->sendHeader("Expires", "-1"); + server->sendHeader("Content-Length", String(message.length())); + server->send ( 404, "text/plain", message ); +} + + +/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ +boolean WiFiManager::captivePortal() { + if (!isIp(server->hostHeader()) ) { + DEBUG_WM(F("Request redirected to captive portal")); + server->sendHeader("Location", String("http://") + toStringIp(server->client().localIP()), true); + server->send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + server->client().stop(); // Stop is needed because we sent no content length + return true; + } + return false; +} + +//start up config portal callback +void WiFiManager::setAPCallback( void (*func)(WiFiManager* myWiFiManager) ) { + _apcallback = func; +} + +//start up save config callback +void WiFiManager::setSaveConfigCallback( void (*func)(void) ) { + _savecallback = func; +} + +//sets a custom element to add to head, like a new style tag +void WiFiManager::setCustomHeadElement(const char* element) { + _customHeadElement = element; +} + +//if this is true, remove duplicated Access Points - defaut true +void WiFiManager::setRemoveDuplicateAPs(boolean removeDuplicates) { + _removeDuplicateAPs = removeDuplicates; +} + + + +template +void WiFiManager::DEBUG_WM(Generic text) { + if (_debug) { + Serial.print("*WM: "); + Serial.println(text); + } +} + +int WiFiManager::getRSSIasQuality(int RSSI) { + int quality = 0; + + if (RSSI <= -100) { + quality = 0; + } else if (RSSI >= -50) { + quality = 100; + } else { + quality = 2 * (RSSI + 100); + } + return quality; +} + +/** Is this an IP? */ +boolean WiFiManager::isIp(String str) { + for (size_t i = 0; i < str.length(); i++) { + int c = str.charAt(i); + if (c != '.' && (c < '0' || c > '9')) { + return false; + } + } + return true; +} + +/** IP to String? */ +String WiFiManager::toStringIp(IPAddress ip) { + String res = ""; + for (int i = 0; i < 3; i++) { + res += String((ip >> (8 * i)) & 0xFF) + "."; + } + res += String(((ip >> 8 * 3)) & 0xFF); + return res; +} diff --git a/WiFiManager.h b/src/WiFiManager.h similarity index 97% rename from WiFiManager.h rename to src/WiFiManager.h index 28ff8f4..136dde0 100644 --- a/WiFiManager.h +++ b/src/WiFiManager.h @@ -1,203 +1,203 @@ -/************************************************************** - WiFiManager is a library for the ESP8266/Arduino platform - (https://github.com/esp8266/Arduino) to enable easy - configuration and reconfiguration of WiFi credentials using a Captive Portal - inspired by: - http://www.esp8266.com/viewtopic.php?f=29&t=2520 - https://github.com/chriscook8/esp-arduino-apboot - https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced - Built by AlexT https://github.com/tzapu - Licensed under MIT license - **************************************************************/ - -#ifndef WiFiManager_h -#define WiFiManager_h - -#include -#include -#include -#include - -extern "C" { - #include "user_interface.h" -} - -const char HTTP_HEADER[] PROGMEM = "{v}"; -const char HTTP_STYLE[] PROGMEM = ""; -const char HTTP_SCRIPT[] PROGMEM = ""; -const char HTTP_HEADER_END[] PROGMEM = "
"; -const char HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; -const char HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; -const char HTTP_FORM_START[] PROGMEM = "


"; -const char HTTP_FORM_PARAM[] PROGMEM = "
"; -const char HTTP_FORM_END[] PROGMEM = "
"; -const char HTTP_SCAN_LINK[] PROGMEM = "
"; -const char HTTP_SAVED[] PROGMEM = "
Credentials Saved
Trying to connect ESP to network.
If it fails reconnect to AP to try again
"; -const char HTTP_END[] PROGMEM = "
"; - -#ifndef WIFI_MANAGER_MAX_PARAMS -#define WIFI_MANAGER_MAX_PARAMS 10 -#endif - -class WiFiManagerParameter { - public: - /** - Create custom parameters that can be added to the WiFiManager setup web page - @id is used for HTTP queries and must not contain spaces nor other special characters - */ - WiFiManagerParameter(const char *custom); - WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length); - WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); - ~WiFiManagerParameter(); - - const char *getID(); - const char *getValue(); - const char *getPlaceholder(); - int getValueLength(); - const char *getCustomHTML(); - private: - const char *_id; - const char *_placeholder; - char *_value; - int _length; - const char *_customHTML; - - void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); - - friend class WiFiManager; -}; - - -class WiFiManager -{ - public: - WiFiManager(); - ~WiFiManager(); - - boolean autoConnect(); - boolean autoConnect(char const *apName, char const *apPassword = NULL); - - //if you want to always start the config portal, without trying to connect first - boolean startConfigPortal(); - boolean startConfigPortal(char const *apName, char const *apPassword = NULL); - - // get the AP name of the config portal, so it can be used in the callback - String getConfigPortalSSID(); - - void resetSettings(); - - //sets timeout before webserver loop ends and exits even if there has been no setup. - //useful for devices that failed to connect at some point and got stuck in a webserver loop - //in seconds setConfigPortalTimeout is a new name for setTimeout - void setConfigPortalTimeout(unsigned long seconds); - void setTimeout(unsigned long seconds); - - //sets timeout for which to attempt connecting, useful if you get a lot of failed connects - void setConnectTimeout(unsigned long seconds); - - - void setDebugOutput(boolean debug); - //defaults to not showing anything under 8% signal quality if called - void setMinimumSignalQuality(int quality = 8); - //sets a custom ip /gateway /subnet configuration - void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); - //sets config for a static IP - void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); - //called when AP mode and config portal is started - void setAPCallback( void (*func)(WiFiManager*) ); - //called when settings have been changed and connection was successful - void setSaveConfigCallback( void (*func)(void) ); - //adds a custom parameter, returns false on failure - bool addParameter(WiFiManagerParameter *p); - //if this is set, it will exit after config, even if connection is unsuccessful. - void setBreakAfterConfig(boolean shouldBreak); - //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) - //TODO - //if this is set, customise style - void setCustomHeadElement(const char* element); - //if this is true, remove duplicated Access Points - defaut true - void setRemoveDuplicateAPs(boolean removeDuplicates); - - private: - std::unique_ptr dnsServer; - std::unique_ptr server; - - //const int WM_DONE = 0; - //const int WM_WAIT = 10; - - //const String HTTP_HEADER = "{v}"; - - void setupConfigPortal(); - void startWPS(); - - const char* _apName = "no-net"; - const char* _apPassword = NULL; - String _ssid = ""; - String _pass = ""; - unsigned long _configPortalTimeout = 0; - unsigned long _connectTimeout = 0; - unsigned long _configPortalStart = 0; - - IPAddress _ap_static_ip; - IPAddress _ap_static_gw; - IPAddress _ap_static_sn; - IPAddress _sta_static_ip; - IPAddress _sta_static_gw; - IPAddress _sta_static_sn; - - int _paramsCount = 0; - int _minimumQuality = -1; - boolean _removeDuplicateAPs = true; - boolean _shouldBreakAfterConfig = false; - boolean _tryWPS = false; - - const char* _customHeadElement = ""; - - //String getEEPROMString(int start, int len); - //void setEEPROMString(int start, int len, String string); - - int status = WL_IDLE_STATUS; - int connectWifi(String ssid, String pass); - uint8_t waitForConnectResult(); - - void handleRoot(); - void handleWifi(boolean scan); - void handleWifiSave(); - void handleInfo(); - void handleReset(); - void handleNotFound(); - void handle204(); - boolean captivePortal(); - boolean configPortalHasTimeout(); - - // DNS server - const byte DNS_PORT = 53; - - //helpers - int getRSSIasQuality(int RSSI); - boolean isIp(String str); - String toStringIp(IPAddress ip); - - boolean connect; - boolean _debug = true; - - void (*_apcallback)(WiFiManager*) = NULL; - void (*_savecallback)(void) = NULL; - - int _max_params; - WiFiManagerParameter** _params; - - template - void DEBUG_WM(Generic text); - - template - auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) { - return obj->fromString(s); - } - auto optionalIPFromString(...) -> bool { - DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); - return false; - } -}; - -#endif +/************************************************************** + WiFiManager is a library for the ESP8266/Arduino platform + (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal + inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer/examples/CaptivePortalAdvanced + Built by AlexT https://github.com/tzapu + Licensed under MIT license + **************************************************************/ + +#ifndef WiFiManager_h +#define WiFiManager_h + +#include +#include +#include +#include + +extern "C" { + #include "user_interface.h" +} + +const char HTTP_HEADER[] PROGMEM = "{v}"; +const char HTTP_STYLE[] PROGMEM = ""; +const char HTTP_SCRIPT[] PROGMEM = ""; +const char HTTP_HEADER_END[] PROGMEM = "
"; +const char HTTP_PORTAL_OPTIONS[] PROGMEM = "



"; +const char HTTP_ITEM[] PROGMEM = "
{v} {r}%
"; +const char HTTP_FORM_START[] PROGMEM = "


"; +const char HTTP_FORM_PARAM[] PROGMEM = "
"; +const char HTTP_FORM_END[] PROGMEM = "
"; +const char HTTP_SCAN_LINK[] PROGMEM = "
"; +const char HTTP_SAVED[] PROGMEM = "
Credentials Saved
Trying to connect ESP to network.
If it fails reconnect to AP to try again
"; +const char HTTP_END[] PROGMEM = "
"; + +#ifndef WIFI_MANAGER_MAX_PARAMS +#define WIFI_MANAGER_MAX_PARAMS 10 +#endif + +class WiFiManagerParameter { + public: + /** + Create custom parameters that can be added to the WiFiManager setup web page + @id is used for HTTP queries and must not contain spaces nor other special characters + */ + WiFiManagerParameter(const char *custom); + WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length); + WiFiManagerParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); + ~WiFiManagerParameter(); + + const char *getID(); + const char *getValue(); + const char *getPlaceholder(); + int getValueLength(); + const char *getCustomHTML(); + private: + const char *_id; + const char *_placeholder; + char *_value; + int _length; + const char *_customHTML; + + void init(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom); + + friend class WiFiManager; +}; + + +class WiFiManager +{ + public: + WiFiManager(); + ~WiFiManager(); + + boolean autoConnect(); + boolean autoConnect(char const *apName, char const *apPassword = NULL); + + //if you want to always start the config portal, without trying to connect first + boolean startConfigPortal(); + boolean startConfigPortal(char const *apName, char const *apPassword = NULL); + + // get the AP name of the config portal, so it can be used in the callback + String getConfigPortalSSID(); + + void resetSettings(); + + //sets timeout before webserver loop ends and exits even if there has been no setup. + //useful for devices that failed to connect at some point and got stuck in a webserver loop + //in seconds setConfigPortalTimeout is a new name for setTimeout + void setConfigPortalTimeout(unsigned long seconds); + void setTimeout(unsigned long seconds); + + //sets timeout for which to attempt connecting, useful if you get a lot of failed connects + void setConnectTimeout(unsigned long seconds); + + + void setDebugOutput(boolean debug); + //defaults to not showing anything under 8% signal quality if called + void setMinimumSignalQuality(int quality = 8); + //sets a custom ip /gateway /subnet configuration + void setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); + //sets config for a static IP + void setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn); + //called when AP mode and config portal is started + void setAPCallback( void (*func)(WiFiManager*) ); + //called when settings have been changed and connection was successful + void setSaveConfigCallback( void (*func)(void) ); + //adds a custom parameter, returns false on failure + bool addParameter(WiFiManagerParameter *p); + //if this is set, it will exit after config, even if connection is unsuccessful. + void setBreakAfterConfig(boolean shouldBreak); + //if this is set, try WPS setup when starting (this will delay config portal for up to 2 mins) + //TODO + //if this is set, customise style + void setCustomHeadElement(const char* element); + //if this is true, remove duplicated Access Points - defaut true + void setRemoveDuplicateAPs(boolean removeDuplicates); + + private: + std::unique_ptr dnsServer; + std::unique_ptr server; + + //const int WM_DONE = 0; + //const int WM_WAIT = 10; + + //const String HTTP_HEADER = "{v}"; + + void setupConfigPortal(); + void startWPS(); + + const char* _apName = "no-net"; + const char* _apPassword = NULL; + String _ssid = ""; + String _pass = ""; + unsigned long _configPortalTimeout = 0; + unsigned long _connectTimeout = 0; + unsigned long _configPortalStart = 0; + + IPAddress _ap_static_ip; + IPAddress _ap_static_gw; + IPAddress _ap_static_sn; + IPAddress _sta_static_ip; + IPAddress _sta_static_gw; + IPAddress _sta_static_sn; + + int _paramsCount = 0; + int _minimumQuality = -1; + boolean _removeDuplicateAPs = true; + boolean _shouldBreakAfterConfig = false; + boolean _tryWPS = false; + + const char* _customHeadElement = ""; + + //String getEEPROMString(int start, int len); + //void setEEPROMString(int start, int len, String string); + + int status = WL_IDLE_STATUS; + int connectWifi(String ssid, String pass); + uint8_t waitForConnectResult(); + + void handleRoot(); + void handleWifi(boolean scan); + void handleWifiSave(); + void handleInfo(); + void handleReset(); + void handleNotFound(); + void handle204(); + boolean captivePortal(); + boolean configPortalHasTimeout(); + + // DNS server + const byte DNS_PORT = 53; + + //helpers + int getRSSIasQuality(int RSSI); + boolean isIp(String str); + String toStringIp(IPAddress ip); + + boolean connect; + boolean _debug = true; + + void (*_apcallback)(WiFiManager*) = NULL; + void (*_savecallback)(void) = NULL; + + int _max_params; + WiFiManagerParameter** _params; + + template + void DEBUG_WM(Generic text); + + template + auto optionalIPFromString(T *obj, const char *s) -> decltype( obj->fromString(s) ) { + return obj->fromString(s); + } + auto optionalIPFromString(...) -> bool { + DEBUG_WM("NO fromString METHOD ON IPAddress, you need ESP8266 core 2.1.0 or newer for Custom IP configuration to work."); + return false; + } +}; + +#endif diff --git a/Words.h b/src/Words.h similarity index 94% rename from Words.h rename to src/Words.h index 639110e..51c23e7 100644 --- a/Words.h +++ b/src/Words.h @@ -80,19 +80,19 @@ #define DE_HALB matrix[4] |= 0b1111000000000000 #define DE_DREIVIERTEL matrix[2] |= 0b1111111111100000 -#define DE_H_EIN matrix[5] |= 0b1110000000000000 -#define DE_H_EINS matrix[5] |= 0b1111000000000000 -#define DE_H_ZWEI matrix[5] |= 0b0000000111100000 -#define DE_H_DREI matrix[6] |= 0b1111000000000000 -#define DE_H_VIER matrix[6] |= 0b0000000111100000 -#define DE_H_FUENF matrix[4] |= 0b0000000111100000 -#define DE_H_SECHS matrix[7] |= 0b1111100000000000 -#define DE_H_SIEBEN matrix[8] |= 0b1111110000000000 -#define DE_H_ACHT matrix[7] |= 0b0000000111100000 -#define DE_H_NEUN matrix[9] |= 0b0001111000000000 -#define DE_H_ZEHN matrix[9] |= 0b1111000000000000 -#define DE_H_ELF matrix[4] |= 0b0000011100000000 -#define DE_H_ZWOELF matrix[8] |= 0b0000001111100000 +#define DE_H_EIN matrix[5] |= 0b0011100000000000 +#define DE_H_EINS matrix[5] |= 0b0011110000000000 +#define DE_H_ZWEI matrix[5] |= 0b1111000000000000 +#define DE_H_DREI matrix[6] |= 0b0111100000000000 +#define DE_H_VIER matrix[7] |= 0b0000000111100000 +#define DE_H_FUENF matrix[6] |= 0b0000000111100000 +#define DE_H_SECHS matrix[9] |= 0b0111110000000000 +#define DE_H_SIEBEN matrix[5] |= 0b0000011111100000 +#define DE_H_ACHT matrix[8] |= 0b0111100000000000 +#define DE_H_NEUN matrix[7] |= 0b0001111000000000 +#define DE_H_ZEHN matrix[8] |= 0b0000001111000000 +#define DE_H_ELF matrix[7] |= 0b1110000000000000 +#define DE_H_ZWOELF matrix[4] |= 0b0000001111100000 #endif @@ -133,7 +133,7 @@ #define EN_ITIS matrix[0] |= 0b1101100000000000 #define EN_TIME matrix[0] |= 0b0000000111100000 #define EN_A matrix[1] |= 0b1000000000000000 -#define EN_OCLOCK matrix[9] |= 0b0000011111100000 +#define EN_OCLOCK matrix[9] |= 0b0000111111100000 #define EN_AM matrix[0] |= 0b0000000110000000 #define EN_PM matrix[0] |= 0b0000000001100000 diff --git a/misc/BOM.txt b/src/misc/BOM.txt similarity index 95% rename from misc/BOM.txt rename to src/misc/BOM.txt index f73efca..4c53a90 100644 --- a/misc/BOM.txt +++ b/src/misc/BOM.txt @@ -1,30 +1,30 @@ --------------------------------------------------------------- - -1x WeMos D1 mini -115x SK6812 or WS2812B RGB(W) LED-Stripe, 30 LEDs per meter -1x DS3231 RTC Module -1x DHT22 Module -1x 145475 LDR A9013 -1x HX1838 IR-Remote -1x 171085 IR-Receiver TSOP31240 -3x Button -1x Powersupply 5V, 4A - --------------------------------------------------------------- - -1x Baseplate 450 x 450 x 2 mm - -Outer frame: -2x Bar 450 x 20 x 15 mm -2x Bar 420 x 20 x 15 mm - -Inner frame: -2x Bar 355 x 20 x 15 mm -2x Bar 325 x 20 x 15 mm -8x Supermagnets 10 x 5 mm - -Light grid: -12x Bar 325 x 20 x 5 mm -99x Bar 23 x 20 x 5 mm - --------------------------------------------------------------- +-------------------------------------------------------------- + +1x WeMos D1 mini +115x SK6812 or WS2812B RGB(W) LED-Stripe, 30 LEDs per meter +1x DS3231 RTC Module +1x DHT22 Module +1x 145475 LDR A9013 +1x HX1838 IR-Remote +1x 171085 IR-Receiver TSOP31240 +3x Button +1x Powersupply 5V, 4A + +-------------------------------------------------------------- + +1x Baseplate 450 x 450 x 2 mm + +Outer frame: +2x Bar 450 x 20 x 15 mm +2x Bar 420 x 20 x 15 mm + +Inner frame: +2x Bar 355 x 20 x 15 mm +2x Bar 325 x 20 x 15 mm +8x Supermagnets 10 x 5 mm + +Light grid: +12x Bar 325 x 20 x 5 mm +99x Bar 23 x 20 x 5 mm + +-------------------------------------------------------------- diff --git a/misc/Clock_45x45.dxf b/src/misc/Clock_45x45.dxf similarity index 84% rename from misc/Clock_45x45.dxf rename to src/misc/Clock_45x45.dxf index a22f6e3..d16e193 100644 --- a/misc/Clock_45x45.dxf +++ b/src/misc/Clock_45x45.dxf @@ -1,15634 +1,15634 @@ -999 -dxfrw 0.6.3 - 0 -SECTION - 2 -HEADER - 9 -$ACADVER - 1 -AC1021 - 9 -$DWGCODEPAGE - 3 -ANSI_1252 - 9 -$INSBASE - 10 -0 - 20 -0 - 30 -0 - 9 -$EXTMIN - 10 --37.81250000000001 - 20 --33.125 - 30 -0 - 9 -$EXTMAX - 10 -483.125 - 20 -487.8125 - 30 -0 - 9 -$LIMMIN - 10 -0 - 20 -0 - 9 -$LIMMAX - 10 -420 - 20 -297 - 9 -$ORTHOMODE - 70 - 0 - 9 -$REGENMODE - 70 - 1 - 9 -$FILLMODE - 70 - 1 - 9 -$QTEXTMODE - 70 - 0 - 9 -$MIRRTEXT - 70 - 0 - 9 -$LTSCALE - 40 -1 - 9 -$ATTMODE - 70 - 0 - 9 -$TEXTSIZE - 40 -2.5 - 9 -$TRACEWID - 40 -15.68 - 9 -$TEXTSTYLE - 7 -STANDARD - 9 -$CLAYER - 8 -0 - 9 -$CELTYPE - 6 -BYLAYER - 9 -$CECOLOR - 62 - 256 - 9 -$CELTSCALE - 40 -1 - 9 -$DISPSILH - 70 - 0 - 9 -$DIMSCALE - 40 -2.5 - 9 -$DIMASZ - 40 -2.5 - 9 -$DIMEXO - 40 -0.625 - 9 -$DIMDLI - 40 -3.75 - 9 -$DIMRND - 40 -0 - 9 -$DIMDLE - 40 -0 - 9 -$DIMEXE - 40 -1.25 - 9 -$DIMTP - 40 -0 - 9 -$DIMTM - 40 -0 - 9 -$DIMTXT - 40 -2.5 - 9 -$DIMCEN - 40 -2.5 - 9 -$DIMTSZ - 40 -0 - 9 -$DIMTOL - 70 - 0 - 9 -$DIMLIM - 70 - 0 - 9 -$DIMTIH - 70 - 0 - 9 -$DIMTOH - 70 - 0 - 9 -$DIMSE1 - 70 - 0 - 9 -$DIMSE2 - 70 - 0 - 9 -$DIMTAD - 70 - 1 - 9 -$DIMZIN - 70 - 8 - 9 -$DIMBLK - 1 - - 9 -$DIMASO - 70 - 1 - 9 -$DIMSHO - 70 - 1 - 9 -$DIMPOST - 1 - - 9 -$DIMAPOST - 1 - - 9 -$DIMALT - 70 - 0 - 9 -$DIMALTD - 70 - 3 - 9 -$DIMALTF - 40 -0.03937 - 9 -$DIMLFAC - 40 -1 - 9 -$DIMTOFL - 70 - 1 - 9 -$DIMTVP - 40 -0 - 9 -$DIMTIX - 70 - 0 - 9 -$DIMSOXD - 70 - 0 - 9 -$DIMSAH - 70 - 0 - 9 -$DIMBLK1 - 1 - - 9 -$DIMBLK2 - 1 - - 9 -$DIMSTYLE - 2 -STANDARD - 9 -$DIMCLRD - 70 - 0 - 9 -$DIMCLRE - 70 - 0 - 9 -$DIMCLRT - 70 - 0 - 9 -$DIMTFAC - 40 -1 - 9 -$DIMGAP - 40 -0.625 - 9 -$DIMJUST - 70 - 0 - 9 -$DIMSD1 - 70 - 0 - 9 -$DIMSD2 - 70 - 0 - 9 -$DIMTOLJ - 70 - 0 - 9 -$DIMTZIN - 70 - 8 - 9 -$DIMALTZ - 70 - 0 - 9 -$DIMALTTZ - 70 - 0 - 9 -$DIMUPT - 70 - 0 - 9 -$DIMDEC - 70 - 2 - 9 -$DIMTDEC - 70 - 2 - 9 -$DIMALTU - 70 - 2 - 9 -$DIMALTTD - 70 - 3 - 9 -$DIMTXSTY - 7 -STANDARD - 9 -$DIMAUNIT - 70 - 0 - 9 -$DIMADEC - 70 - 0 - 9 -$DIMALTRND - 40 -0 - 9 -$DIMAZIN - 70 - 0 - 9 -$DIMDSEP - 70 - 44 - 9 -$DIMATFIT - 70 - 3 - 9 -$DIMFRAC - 70 - 0 - 9 -$DIMLDRBLK - 1 -STANDARD - 9 -$DIMLUNIT - 70 - 2 - 9 -$DIMLWD - 70 - -2 - 9 -$DIMLWE - 70 - -2 - 9 -$DIMTMOVE - 70 - 0 - 9 -$DIMFXL - 40 -1 - 9 -$DIMFXLON - 70 - 0 - 9 -$DIMJOGANG - 40 -0.7854 - 9 -$DIMTFILL - 70 - 0 - 9 -$DIMTFILLCLR - 70 - 0 - 9 -$DIMARCSYM - 70 - 0 - 9 -$DIMLTYPE - 6 - - 9 -$DIMLTEX1 - 6 - - 9 -$DIMLTEX2 - 6 - - 9 -$LUNITS - 70 - 2 - 9 -$LUPREC - 70 - 4 - 9 -$SKETCHINC - 40 -1 - 9 -$FILLETRAD - 40 -0 - 9 -$AUNITS - 70 - 0 - 9 -$AUPREC - 70 - 2 - 9 -$MENU - 1 -. - 9 -$ELEVATION - 40 -0 - 9 -$PELEVATION - 40 -0 - 9 -$THICKNESS - 40 -0 - 9 -$LIMCHECK - 70 - 0 - 9 -$CHAMFERA - 40 -0 - 9 -$CHAMFERB - 40 -0 - 9 -$CHAMFERC - 40 -0 - 9 -$CHAMFERD - 40 -0 - 9 -$SKPOLY - 70 - 0 - 9 -$USRTIMER - 70 - 1 - 9 -$ANGBASE - 50 -0 - 9 -$ANGDIR - 70 - 0 - 9 -$PDMODE - 70 - 34 - 9 -$PDSIZE - 40 -0 - 9 -$PLINEWID - 40 -0 - 9 -$SPLFRAME - 70 - 0 - 9 -$SPLINETYPE - 70 - 2 - 9 -$SPLINESEGS - 70 - 8 - 9 -$HANDSEED - 5 -20000 - 9 -$SURFTAB1 - 70 - 6 - 9 -$SURFTAB2 - 70 - 6 - 9 -$SURFTYPE - 70 - 6 - 9 -$SURFU - 70 - 6 - 9 -$SURFV - 70 - 6 - 9 -$UCSBASE - 2 - - 9 -$UCSNAME - 2 - - 9 -$UCSORG - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSXDIR - 10 -1 - 20 -0 - 30 -0 - 9 -$UCSYDIR - 10 -0 - 20 -1 - 30 -0 - 9 -$UCSORTHOREF - 2 - - 9 -$UCSORTHOVIEW - 70 - 0 - 9 -$UCSORGTOP - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSORGBOTTOM - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSORGLEFT - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSORGRIGHT - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSORGFRONT - 10 -0 - 20 -0 - 30 -0 - 9 -$UCSORGBACK - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSBASE - 2 - - 9 -$PUCSNAME - 2 - - 9 -$PUCSORG - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSXDIR - 10 -1 - 20 -0 - 30 -0 - 9 -$PUCSYDIR - 10 -0 - 20 -1 - 30 -0 - 9 -$PUCSORTHOREF - 2 - - 9 -$PUCSORTHOVIEW - 70 - 0 - 9 -$PUCSORGTOP - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSORGBOTTOM - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSORGLEFT - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSORGRIGHT - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSORGFRONT - 10 -0 - 20 -0 - 30 -0 - 9 -$PUCSORGBACK - 10 -0 - 20 -0 - 30 -0 - 9 -$USERI1 - 70 - 0 - 9 -$USERI2 - 70 - 0 - 9 -$USERI3 - 70 - 0 - 9 -$USERI4 - 70 - 0 - 9 -$USERI5 - 70 - 0 - 9 -$USERR1 - 40 -0 - 9 -$USERR2 - 40 -0 - 9 -$USERR3 - 40 -0 - 9 -$USERR4 - 40 -0 - 9 -$USERR5 - 40 -0 - 9 -$WORLDVIEW - 70 - 1 - 9 -$SHADEDGE - 70 - 3 - 9 -$SHADEDIF - 70 - 70 - 9 -$TILEMODE - 70 - 1 - 9 -$MAXACTVP - 70 - 64 - 9 -$PINSBASE - 10 -12.5 - 20 -56 - 30 -0 - 9 -$PLIMCHECK - 70 - 0 - 9 -$PEXTMIN - 10 -0 - 20 -0 - 30 -0 - 9 -$PEXTMAX - 10 -0 - 20 -0 - 30 -0 - 9 -$GRIDMODE - 70 - 1 - 9 -$SNAPSTYLE - 70 - 0 - 9 -$PLIMMIN - 10 -0 - 20 -0 - 9 -$PLIMMAX - 10 -210 - 20 -297 - 9 -$UNITMODE - 70 - 0 - 9 -$VISRETAIN - 70 - 1 - 9 -$PLINEGEN - 70 - 0 - 9 -$PSLTSCALE - 70 - 1 - 9 -$TREEDEPTH - 70 - 3020 - 9 -$CMLSTYLE - 2 -Standard - 9 -$CMLJUST - 70 - 0 - 9 -$CMLSCALE - 40 -20 - 9 -$PROXYGRAPHICS - 70 - 1 - 9 -$MEASUREMENT - 70 - 1 - 9 -$CELWEIGHT -370 - -1 - 9 -$ENDCAPS -280 - 0 - 9 -$JOINSTYLE -280 - 0 - 9 -$LWDISPLAY -290 - 0 - 9 -$INSUNITS - 70 - 4 - 9 -$HYPERLINKBASE - 1 - - 9 -$STYLESHEET - 1 - - 9 -$XEDIT -290 - 1 - 9 -$CEPSNTYPE -380 - 0 - 9 -$PSTYLEMODE -290 - 1 - 9 -$EXTNAMES -290 - 1 - 9 -$PSVPSCALE - 40 -0.4111115222226333 - 9 -$OLESTARTUP -290 - 0 - 9 -$SORTENTS -280 - 127 - 9 -$INDEXCTL -280 - 0 - 9 -$HIDETEXT -280 - 1 - 9 -$XCLIPFRAME -290 - 0 - 9 -$HALOGAP -280 - 0 - 9 -$OBSCOLOR - 70 - 257 - 9 -$OBSLTYPE -280 - 0 - 9 -$INTERSECTIONDISPLAY -280 - 0 - 9 -$INTERSECTIONCOLOR - 70 - 257 - 9 -$DIMASSOC -280 - 1 - 9 -$PROJECTNAME - 1 - - 9 -$CAMERADISPLAY -290 - 0 - 9 -$LENSLENGTH - 40 -50 - 9 -$CAMERAHEIGHT - 40 -0 - 9 -$STEPSPERSEC - 40 -2 - 9 -$STEPSIZE - 40 -50 - 9 -$3DDWFPREC - 40 -2 - 9 -$PSOLWIDTH - 40 -5 - 9 -$PSOLHEIGHT - 40 -80 - 9 -$LOFTANG1 - 40 -1.570796326794897 - 9 -$LOFTANG2 - 40 -1.570796326794897 - 9 -$LOFTMAG1 - 40 -0 - 9 -$LOFTMAG2 - 40 -0 - 9 -$LOFTPARAM - 70 - 7 - 9 -$LOFTNORMALS -280 - 1 - 9 -$LATITUDE - 40 -1 - 9 -$LONGITUDE - 40 -1 - 9 -$NORTHDIRECTION - 40 -0 - 9 -$TIMEZONE - 70 --8000 - 9 -$LIGHTGLYPHDISPLAY -280 - 1 - 9 -$TILEMODELIGHTSYNCH -280 - 1 - 9 -$SOLIDHIST -280 - 1 - 9 -$SHOWHIST -280 - 1 - 9 -$DWFFRAME -280 - 2 - 9 -$DGNFRAME -280 - 0 - 9 -$REALWORLDSCALE -290 - 1 - 9 -$INTERFERECOLOR - 62 - 1 - 9 -$CSHADOW -280 - 0 - 9 -$SHADOWPLANELOCATION - 40 -0 - 0 -ENDSEC - 0 -SECTION - 2 -CLASSES - 0 -ENDSEC - 0 -SECTION - 2 -TABLES - 0 -TABLE - 2 -VPORT - 5 -8 -330 -0 -100 -AcDbSymbolTable - 70 - 1 - 0 -VPORT - 5 -31 -330 -2 -100 -AcDbSymbolTableRecord -100 -AcDbViewportTableRecord - 2 -*ACTIVE - 70 - 0 - 10 -0 - 20 -0 - 11 -1 - 21 -1 - 12 -362.5794227574751 - 22 -245.46944213732 - 13 -0 - 23 -0 - 14 -10 - 24 -10 - 15 -10 - 25 -10 - 16 -0 - 26 -0 - 36 -1 - 17 -0 - 27 -0 - 37 -0 - 40 -526.7064645625692 - 41 -1.907995618838992 - 42 -50 - 43 -0 - 44 -0 - 50 -0 - 51 -0 - 71 - 0 - 72 - 100 - 73 - 1 - 74 - 3 - 75 - 0 - 76 - 1 - 77 - 0 - 78 - 0 -281 - 0 - 65 - 1 -110 -0 -120 -0 -130 -0 -111 -1 -121 -0 -131 -0 -112 -0 -122 -1 -132 -0 - 79 - 0 -146 -0 -348 -10020 - 60 - 7 - 61 - 5 -292 -1 -282 - 1 -141 -0 -142 -0 - 63 - 250 -421 -3358443 - 0 -ENDTAB - 0 -TABLE - 2 -LTYPE - 5 -5 -330 -0 -100 -AcDbSymbolTable - 70 - 4 - 0 -LTYPE - 5 -14 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -ByBlock - 70 - 0 - 3 - - 72 - 65 - 73 - 0 - 40 -0 - 0 -LTYPE - 5 -15 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -ByLayer - 70 - 0 - 3 - - 72 - 65 - 73 - 0 - 40 -0 - 0 -LTYPE - 5 -16 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -Continuous - 70 - 0 - 3 -Solid line - 72 - 65 - 73 - 0 - 40 -0 - 0 -LTYPE - 5 -32 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DOT - 70 - 0 - 3 -Dot . . . . . . . . . . . . . . . . . . . . . . - 72 - 65 - 73 - 2 - 40 -6.35 - 49 -0 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -33 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DOTTINY - 70 - 0 - 3 -Dot (.15x) ..................................... - 72 - 65 - 73 - 2 - 40 -0.9525 - 49 -0 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -34 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DOT2 - 70 - 0 - 3 -Dot (.5x) ..................................... - 72 - 65 - 73 - 2 - 40 -3.175 - 49 -0 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -35 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DOTX2 - 70 - 0 - 3 -Dot (2x) . . . . . . . . . . . . . - 72 - 65 - 73 - 2 - 40 -12.7 - 49 -0 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -LTYPE - 5 -36 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHED - 70 - 0 - 3 -Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - 72 - 65 - 73 - 2 - 40 -19.05 - 49 -12.7 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -37 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHEDTINY - 70 - 0 - 3 -Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - 72 - 65 - 73 - 2 - 40 -2.8575 - 49 -1.905 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -38 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHED2 - 70 - 0 - 3 -Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - 72 - 65 - 73 - 2 - 40 -9.524999999999999 - 49 -6.35 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -39 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHEDX2 - 70 - 0 - 3 -Dashed (2x) ____ ____ ____ ____ ____ ___ - 72 - 65 - 73 - 2 - 40 -38.09999999999999 - 49 -25.4 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -LTYPE - 5 -3A -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHDOT - 70 - 0 - 3 -Dash dot __ . __ . __ . __ . __ . __ . __ . __ - 72 - 65 - 73 - 4 - 40 -25.4 - 49 -12.7 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -0 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -3B -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHDOTTINY - 70 - 0 - 3 -Dash dot (.15x) _._._._._._._._._._._._._._._. - 72 - 65 - 73 - 4 - 40 -3.81 - 49 -1.905 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -0 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -3C -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHDOT2 - 70 - 0 - 3 -Dash dot (.5x) _._._._._._._._._._._._._._._. - 72 - 65 - 73 - 4 - 40 -12.7 - 49 -6.35 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -0 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -3D -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DASHDOTX2 - 70 - 0 - 3 -Dash dot (2x) ____ . ____ . ____ . ___ - 72 - 65 - 73 - 4 - 40 -50.8 - 49 -25.4 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -0 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -LTYPE - 5 -3E -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DIVIDE - 70 - 0 - 3 -Divide ____ . . ____ . . ____ . . ____ . . ____ - 72 - 65 - 73 - 6 - 40 -31.75 - 49 -12.7 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -0 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -0 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -3F -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DIVIDETINY - 70 - 0 - 3 -Divide (.15x) __..__..__..__..__..__..__..__.._ - 72 - 65 - 73 - 6 - 40 -4.7625 - 49 -1.905 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -0 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -0 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -40 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DIVIDE2 - 70 - 0 - 3 -Divide (.5x) __..__..__..__..__..__..__..__.._ - 72 - 65 - 73 - 6 - 40 -15.875 - 49 -6.35 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -0 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -0 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -41 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -DIVIDEX2 - 70 - 0 - 3 -Divide (2x) ________ . . ________ . . _ - 72 - 65 - 73 - 6 - 40 -63.5 - 49 -25.4 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -0 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -0 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -LTYPE - 5 -42 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -BORDER - 70 - 0 - 3 -Border __ __ . __ __ . __ __ . __ __ . __ __ . - 72 - 65 - 73 - 6 - 40 -44.45 - 49 -12.7 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -12.7 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -0 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -43 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -BORDERTINY - 70 - 0 - 3 -Border (.15x) __.__.__.__.__.__.__.__.__.__.__. - 72 - 65 - 73 - 6 - 40 -6.6675 - 49 -1.905 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -1.905 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -0 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -44 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -BORDER2 - 70 - 0 - 3 -Border (.5x) __.__.__.__.__.__.__.__.__.__.__. - 72 - 65 - 73 - 6 - 40 -22.225 - 49 -6.35 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -6.35 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -0 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -45 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -BORDERX2 - 70 - 0 - 3 -Border (2x) ____ ____ . ____ ____ . ___ - 72 - 65 - 73 - 6 - 40 -88.89999999999999 - 49 -25.4 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -25.4 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -0 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -LTYPE - 5 -46 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -CENTER - 70 - 0 - 3 -Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ - 72 - 65 - 73 - 4 - 40 -50.8 - 49 -31.75 - 74 - 0 - 49 --6.35 - 74 - 0 - 49 -6.35 - 74 - 0 - 49 --6.35 - 74 - 0 - 0 -LTYPE - 5 -47 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -CENTERTINY - 70 - 0 - 3 -Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ - 72 - 65 - 73 - 4 - 40 -7.62 - 49 -4.7625 - 74 - 0 - 49 --0.9525 - 74 - 0 - 49 -0.9525 - 74 - 0 - 49 --0.9525 - 74 - 0 - 0 -LTYPE - 5 -48 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -CENTER2 - 70 - 0 - 3 -Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ - 72 - 65 - 73 - 4 - 40 -28.575 - 49 -19.05 - 74 - 0 - 49 --3.175 - 74 - 0 - 49 -3.175 - 74 - 0 - 49 --3.175 - 74 - 0 - 0 -LTYPE - 5 -49 -330 -5 -100 -AcDbSymbolTableRecord -100 -AcDbLinetypeTableRecord - 2 -CENTERX2 - 70 - 0 - 3 -Center (2x) ________ __ ________ __ _____ - 72 - 65 - 73 - 4 - 40 -101.6 - 49 -63.5 - 74 - 0 - 49 --12.7 - 74 - 0 - 49 -12.7 - 74 - 0 - 49 --12.7 - 74 - 0 - 0 -ENDTAB - 0 -TABLE - 2 -LAYER - 5 -2 -330 -0 -100 -AcDbSymbolTable - 70 - 1 - 0 -LAYER - 5 -10 -330 -2 -100 -AcDbSymbolTableRecord -100 -AcDbLayerTableRecord - 2 -0 - 70 - 0 - 62 - 7 - 6 -CONTINUOUS -370 - 0 -390 -F - 0 -LAYER - 5 -4A -330 -2 -100 -AcDbSymbolTableRecord -100 -AcDbLayerTableRecord - 2 -Dimensions - 70 - 0 - 62 - 136 -420 -32896 - 6 -CONTINUOUS -370 - 0 -390 -F - 0 -LAYER - 5 -4B -330 -2 -100 -AcDbSymbolTableRecord -100 -AcDbLayerTableRecord - 2 -LEDs - 70 - 0 - 62 - 2 - 6 -CONTINUOUS -370 - 0 -390 -F - 0 -ENDTAB - 0 -TABLE - 2 -STYLE - 5 -3 -330 -0 -100 -AcDbSymbolTable - 70 - 3 - 0 -STYLE - 5 -4C -330 -2 -100 -AcDbSymbolTableRecord -100 -AcDbTextStyleTableRecord - 2 -Standard - 70 - 0 - 40 -0 - 41 -1 - 50 -0 - 71 - 0 - 42 -1 - 3 -txt - 4 - - 0 -ENDTAB - 0 -TABLE - 2 -VIEW - 5 -6 -330 -0 -100 -AcDbSymbolTable - 70 - 0 - 0 -ENDTAB - 0 -TABLE - 2 -UCS - 5 -7 -330 -0 -100 -AcDbSymbolTable - 70 - 0 - 0 -ENDTAB - 0 -TABLE - 2 -APPID - 5 -9 -330 -0 -100 -AcDbSymbolTable - 70 - 1 - 0 -APPID - 5 -12 -330 -9 -100 -AcDbSymbolTableRecord -100 -AcDbRegAppTableRecord - 2 -ACAD - 70 - 0 - 0 -APPID - 5 -4D -330 -9 -100 -AcDbSymbolTableRecord -100 -AcDbRegAppTableRecord - 2 -LibreCad - 70 - 0 - 0 -ENDTAB - 0 -TABLE - 2 -DIMSTYLE - 5 -A -330 -0 -100 -AcDbSymbolTable - 70 - 1 -100 -AcDbDimStyleTable - 71 - 1 - 0 -DIMSTYLE -105 -4E -330 -A -100 -AcDbSymbolTableRecord -100 -AcDbDimStyleTableRecord - 2 -Standard - 70 - 0 - 40 -2.5 - 41 -2.5 - 42 -0.625 - 43 -0.38 - 44 -1.25 - 45 -0 - 46 -0 - 47 -0 - 48 -0 - 49 -1 -140 -2.5 -141 -0.09 -142 -0 -143 -25.4 -144 -1 -145 -0 -146 -1 -147 -0.625 -148 -0 - 71 - 0 - 72 - 0 - 73 - 0 - 74 - 1 - 75 - 0 - 76 - 0 - 77 - 0 - 78 - 8 - 79 - 0 -170 - 0 -171 - 2 -172 - 0 -173 - 0 -174 - 0 -175 - 0 -176 - 0 -177 - 0 -178 - 0 -179 - 0 -271 - 2 -272 - 4 -273 - 2 -274 - 2 -275 - 0 -276 - 0 -277 - 2 -278 - 44 -279 - 0 -280 - 0 -281 - 0 -282 - 0 -283 - 1 -284 - 0 -285 - 0 -286 - 0 -288 - 0 -289 - 3 -340 -STANDARD -341 - -371 - -2 -372 - -2 - 0 -ENDTAB - 0 -TABLE - 2 -BLOCK_RECORD - 5 -1 -330 -0 -100 -AcDbSymbolTable - 70 - 2 - 0 -BLOCK_RECORD - 5 -1F -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*Model_Space - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -1E -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*Paper_Space - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -4F -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D13 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -52 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D19 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -55 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D17 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -58 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D5 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -5B -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D27 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -5E -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D4 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -61 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D12 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -64 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D25 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -67 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D6 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -6A -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D20 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -6D -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D7 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -70 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D1 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -73 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D8 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -76 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D10 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -79 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D15 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -7C -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D14 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -7F -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D23 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -82 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D2 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -85 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D9 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -88 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D3 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -8B -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D24 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -8E -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D11 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -91 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D16 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -94 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D22 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -97 -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D18 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -9A -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D21 - 70 - 0 -280 - 1 -281 - 0 - 0 -BLOCK_RECORD - 5 -9D -330 -1 -100 -AcDbSymbolTableRecord -100 -AcDbBlockTableRecord - 2 -*D26 - 70 - 0 -280 - 1 -281 - 0 - 0 -ENDTAB - 0 -ENDSEC - 0 -SECTION - 2 -BLOCKS - 0 -BLOCK - 5 -20 -330 -1F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*Model_Space - 70 - 0 - 10 -0 - 20 -0 - 30 -0 - 3 -*Model_Space - 1 - - 0 -ENDBLK - 5 -21 -330 -1F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -1C -330 -1B -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*Paper_Space - 70 - 0 - 10 -0 - 20 -0 - 30 -0 - 3 -*Paper_Space - 1 - - 0 -ENDBLK - 5 -1D -330 -1F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -50 -330 -4F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D13 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D13 - 1 - - 0 -LINE - 5 -A0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -67.5 - 20 -30 - 11 -35 - 21 -30 - 0 -SOLID - 5 -A1 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -55 - 20 -30 - 30 -0 - 11 -61.25 - 21 -31.0407116444321 - 31 -0 - 12 -61.25 - 22 -28.9592883555679 - 32 -0 - 13 -61.25 - 23 -28.9592883555679 - 33 -0 - 0 -SOLID - 5 -A2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -47.5 - 20 -30 - 30 -0 - 11 -41.25 - 21 -28.9592883555679 - 31 -0 - 12 -41.25 - 22 -31.0407116444321 - 32 -0 - 13 -41.25 - 23 -31.0407116444321 - 33 -0 - 0 -MTEXT - 5 -A3 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -61.59722222222241 - 20 -34.6875 - 30 -0 - 40 -6.25 - 41 -10.06944444444483 - 71 - 5 - 72 - 1 - 1 -7,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -360 - 73 - 2 - 44 -1 - 0 -LINE - 5 -A4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -55 - 20 -53.4375 - 11 -55 - 21 -26.875 - 0 -LINE - 5 -A5 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -53.4375 - 11 -47.5 - 21 -26.875 - 0 -ENDBLK - 5 -51 -330 -4F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -53 -330 -52 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D19 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D19 - 1 - - 0 -LINE - 5 -A6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -40 - 20 -387.5 - 11 -40 - 21 -349 - 0 -SOLID - 5 -A7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -40 - 20 -387.5 - 30 -0 - 11 -41.0407116444321 - 21 -381.25 - 31 -0 - 12 -38.9592883555679 - 22 -381.25 - 32 -0 - 13 -38.9592883555679 - 23 -381.25 - 33 -0 - 0 -SOLID - 5 -A8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -40 - 20 -349 - 30 -0 - 11 -38.9592883555679 - 21 -355.25 - 31 -0 - 12 -41.0407116444321 - 22 -355.25 - 32 -0 - 13 -41.0407116444321 - 23 -355.25 - 33 -0 - 0 -MTEXT - 5 -A9 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -35.3125 - 20 -368.25 - 30 -0 - 40 -6.25 - 41 -14.93055555555633 - 71 - 5 - 72 - 1 - 1 -38,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -AA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -60.9375 - 20 -387.5 - 11 -36.875 - 21 -387.5 - 0 -LINE - 5 -AB -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -60.9375 - 20 -349 - 11 -36.875 - 21 -349 - 0 -ENDBLK - 5 -54 -330 -52 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -56 -330 -55 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D17 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D17 - 1 - - 0 -LINE - 5 -AC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -420 - 20 -116.5 - 11 -420 - 21 -85.5 - 0 -SOLID - 5 -AD -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -116.5 - 30 -0 - 11 -421.0407116444321 - 21 -110.25 - 31 -0 - 12 -418.9592883555679 - 22 -110.25 - 32 -0 - 13 -418.9592883555679 - 23 -110.25 - 33 -0 - 0 -SOLID - 5 -AE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -85.5 - 30 -0 - 11 -418.9592883555679 - 21 -91.75 - 31 -0 - 12 -421.0407116444321 - 22 -91.75 - 32 -0 - 13 -421.0407116444321 - 23 -91.75 - 33 -0 - 0 -MTEXT - 5 -AF -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -415.3125 - 20 -101 - 30 -0 - 40 -6.25 - 41 -6.250000000000387 - 71 - 5 - 72 - 1 - 1 -31 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -B0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -367.4715909089 - 20 -116.5 - 11 -423.125 - 21 -116.5 - 0 -LINE - 5 -B1 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -367.4715909089 - 20 -85.5 - 11 -423.125 - 21 -85.5 - 0 -ENDBLK - 5 -57 -330 -55 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -59 -330 -58 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D5 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D5 - 1 - - 0 -LINE - 5 -B2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -55.00000000000001 - 20 --20 - 11 -0 - 21 --20 - 0 -SOLID - 5 -B3 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -55.00000000000001 - 20 --20 - 30 -0 - 11 -48.75000000000001 - 21 --21.0407116444321 - 31 -0 - 12 -48.75000000000001 - 22 --18.9592883555679 - 32 -0 - 13 -48.75000000000001 - 23 --18.9592883555679 - 33 -0 - 0 -SOLID - 5 -B4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -0 - 20 --20 - 30 -0 - 11 -6.25 - 21 --18.9592883555679 - 31 -0 - 12 -6.25 - 22 --21.0407116444321 - 32 -0 - 13 -6.25 - 23 --21.0407116444321 - 33 -0 - 0 -MTEXT - 5 -B5 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -27.5 - 20 --15.3125 - 30 -0 - 40 -6.25 - 41 -7.638888888889664 - 71 - 5 - 72 - 1 - 1 -55 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -360 - 73 - 2 - 44 -1 - 0 -LINE - 5 -B6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -55 - 20 -53.4375 - 11 -55.00000000000001 - 21 --23.125 - 0 -LINE - 5 -B7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --2.870171141771197e-016 - 20 -53.4375 - 11 --5.740342283542393e-016 - 21 --23.125 - 0 -ENDBLK - 5 -5A -330 -58 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -5C -330 -5B -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D27 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D27 - 1 - - 0 -LINE - 5 -B8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -128.8636363636 - 20 -413 - 11 -152.0454545454 - 21 -413 - 0 -SOLID - 5 -B9 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -128.8636363636 - 20 -413 - 30 -0 - 11 -135.1136363636 - 21 -414.0407116444321 - 31 -0 - 12 -135.1136363636 - 22 -411.9592883555679 - 32 -0 - 13 -135.1136363636 - 23 -411.9592883555679 - 33 -0 - 0 -SOLID - 5 -BA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -152.0454545454 - 20 -413 - 30 -0 - 11 -145.7954545454 - 21 -411.9592883555679 - 31 -0 - 12 -145.7954545454 - 22 -414.0407116444321 - 32 -0 - 13 -145.7954545454 - 23 -414.0407116444321 - 33 -0 - 0 -MTEXT - 5 -BB -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -140.4545454545 - 20 -417.6875 - 30 -0 - 40 -6.25 - 41 -18.40277777777817 - 71 - 5 - 72 - 1 - 1 -23,18 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -BC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -128.8636363636 - 20 -384.0625 - 11 -128.8636363636 - 21 -416.125 - 0 -LINE - 5 -BD -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -152.0454545454 - 20 -384.0625 - 11 -152.0454545454 - 21 -416.125 - 0 -ENDBLK - 5 -5D -330 -5B -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -5F -330 -5E -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D4 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D4 - 1 - - 0 -LINE - 5 -BE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -480 - 20 -85.50000000000001 - 11 -480 - 21 -0 - 0 -SOLID - 5 -BF -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -480 - 20 -85.50000000000001 - 30 -0 - 11 -481.0407116444321 - 21 -79.25000000000001 - 31 -0 - 12 -478.9592883555679 - 22 -79.25000000000001 - 32 -0 - 13 -478.9592883555679 - 23 -79.25000000000001 - 33 -0 - 0 -SOLID - 5 -C0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -480 - 20 -0 - 30 -0 - 11 -478.9592883555679 - 21 -6.25 - 31 -0 - 12 -481.0407116444321 - 22 -6.25 - 32 -0 - 13 -481.0407116444321 - 23 -6.25 - 33 -0 - 0 -MTEXT - 5 -C1 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -475.3125 - 20 -42.75000000000001 - 30 -0 - 40 -6.25 - 41 -14.93055555555633 - 71 - 5 - 72 - 1 - 1 -85,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -C2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -367.4715909089 - 20 -85.5 - 11 -483.125 - 21 -85.50000000000001 - 0 -LINE - 5 -C3 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -367.4715909089 - 20 -0 - 11 -483.125 - 21 -0 - 0 -ENDBLK - 5 -60 -330 -5E -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -62 -330 -61 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D12 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D12 - 1 - - 0 -LINE - 5 -C4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --10.00000000000001 - 20 -402.5 - 11 --10.00000000000001 - 21 -450 - 0 -SOLID - 5 -C5 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --10.00000000000001 - 20 -402.5 - 30 -0 - 11 --11.04071164443211 - 21 -408.75 - 31 -0 - 12 --8.95928835556791 - 22 -408.75 - 32 -0 - 13 --8.95928835556791 - 23 -408.75 - 33 -0 - 0 -SOLID - 5 -C6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --10.00000000000001 - 20 -450 - 30 -0 - 11 --8.95928835556791 - 21 -443.75 - 31 -0 - 12 --11.04071164443211 - 22 -443.75 - 32 -0 - 13 --11.04071164443211 - 23 -443.75 - 33 -0 - 0 -MTEXT - 5 -C7 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 --14.68750000000001 - 20 -426.25 - 30 -0 - 40 -6.25 - 41 -15.62500000000039 - 71 - 5 - 72 - 1 - 1 -47,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -C8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -46.25943029137293 - 20 -402.5 - 11 --13.12500000000001 - 21 -402.5 - 0 -LINE - 5 -C9 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -46.25943029137293 - 20 -450 - 11 --13.12500000000001 - 21 -450 - 0 -ENDBLK - 5 -63 -330 -61 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -65 -330 -64 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D25 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D25 - 1 - - 0 -LINE - 5 -CA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --29.99999999999997 - 20 -435 - 11 --30 - 21 -15 - 0 -SOLID - 5 -CB -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --29.99999999999997 - 20 -435 - 30 -0 - 11 --28.95928835556787 - 21 -428.75 - 31 -0 - 12 --31.04071164443207 - 22 -428.75 - 32 -0 - 13 --31.04071164443207 - 23 -428.75 - 33 -0 - 0 -SOLID - 5 -CC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --30 - 20 -15 - 30 -0 - 11 --31.0407116444321 - 21 -21.25 - 31 -0 - 12 --28.9592883555679 - 22 -21.25 - 32 -0 - 13 --28.9592883555679 - 23 -21.25 - 33 -0 - 0 -MTEXT - 5 -CD -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 --34.68749999999999 - 20 -225 - 30 -0 - 40 -6.25 - 41 -13.19444444444444 - 71 - 5 - 72 - 1 - 1 -420 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -CE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --1.5625 - 20 -435 - 11 --33.12499999999997 - 21 -435 - 0 -LINE - 5 -CF -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --1.5625 - 20 -15 - 11 --33.125 - 21 -15 - 0 -ENDBLK - 5 -66 -330 -64 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -68 -330 -67 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D6 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D6 - 1 - - 0 -LINE - 5 -D0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -225 - 20 --30 - 11 -0 - 21 --30 - 0 -SOLID - 5 -D1 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -225 - 20 --30 - 30 -0 - 11 -218.75 - 21 --31.0407116444321 - 31 -0 - 12 -218.75 - 22 --28.9592883555679 - 32 -0 - 13 -218.75 - 23 --28.9592883555679 - 33 -0 - 0 -SOLID - 5 -D2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -0 - 20 --30 - 30 -0 - 11 -6.25 - 21 --28.9592883555679 - 31 -0 - 12 -6.25 - 22 --31.0407116444321 - 32 -0 - 13 -6.25 - 23 --31.0407116444321 - 33 -0 - 0 -MTEXT - 5 -D3 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -112.5 - 20 --25.3125 - 30 -0 - 40 -6.25 - 41 -12.50000000000039 - 71 - 5 - 72 - 1 - 1 -225 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -360 - 73 - 2 - 44 -1 - 0 -LINE - 5 -D4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -225 - 20 -53.4375 - 11 -225 - 21 --33.125 - 0 -LINE - 5 -D5 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --2.870171141771197e-016 - 20 -53.4375 - 11 --5.740342283542393e-016 - 21 --33.125 - 0 -ENDBLK - 5 -69 -330 -67 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -6B -330 -6A -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D20 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D20 - 1 - - 0 -LINE - 5 -D6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -40 - 20 -349 - 11 -40 - 21 -318 - 0 -SOLID - 5 -D7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -40 - 20 -349 - 30 -0 - 11 -41.0407116444321 - 21 -342.75 - 31 -0 - 12 -38.9592883555679 - 22 -342.75 - 32 -0 - 13 -38.9592883555679 - 23 -342.75 - 33 -0 - 0 -SOLID - 5 -D8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -40 - 20 -318 - 30 -0 - 11 -38.9592883555679 - 21 -324.25 - 31 -0 - 12 -41.0407116444321 - 22 -324.25 - 32 -0 - 13 -41.0407116444321 - 23 -324.25 - 33 -0 - 0 -MTEXT - 5 -D9 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -35.3125 - 20 -333.5 - 30 -0 - 40 -6.25 - 41 -6.250000000000387 - 71 - 5 - 72 - 1 - 1 -31 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -DA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -60.9375 - 20 -349 - 11 -36.875 - 21 -349 - 0 -LINE - 5 -DB -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -60.9375 - 20 -318 - 11 -36.875 - 21 -318 - 0 -ENDBLK - 5 -6C -330 -6A -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -6E -330 -6D -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D7 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D7 - 1 - - 0 -LINE - 5 -DC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -460 - 11 -402.5 - 21 -460 - 0 -SOLID - 5 -DD -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -47.5 - 20 -460 - 30 -0 - 11 -53.75 - 21 -461.0407116444321 - 31 -0 - 12 -53.75 - 22 -458.9592883555679 - 32 -0 - 13 -53.75 - 23 -458.9592883555679 - 33 -0 - 0 -SOLID - 5 -DE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -402.5 - 20 -460 - 30 -0 - 11 -396.25 - 21 -458.9592883555679 - 31 -0 - 12 -396.25 - 22 -461.0407116444321 - 32 -0 - 13 -396.25 - 23 -461.0407116444321 - 33 -0 - 0 -MTEXT - 5 -DF -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -225 - 20 -464.6875 - 30 -0 - 40 -6.25 - 41 -12.50000000000116 - 71 - 5 - 72 - 1 - 1 -355 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -E0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -404.0625 - 11 -47.5 - 21 -463.125 - 0 -LINE - 5 -E1 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -402.5 - 20 -404.0625 - 11 -402.5 - 21 -463.125 - 0 -ENDBLK - 5 -6F -330 -6D -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -71 -330 -70 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D1 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D1 - 1 - - 0 -LINE - 5 -E2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -425 - 20 --20 - 11 -450 - 21 --20 - 0 -SOLID - 5 -E3 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -425 - 20 --20 - 30 -0 - 11 -431.25 - 21 --18.9592883555679 - 31 -0 - 12 -431.25 - 22 --21.0407116444321 - 32 -0 - 13 -431.25 - 23 --21.0407116444321 - 33 -0 - 0 -SOLID - 5 -E4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -450 - 20 --20 - 30 -0 - 11 -443.75 - 21 --21.0407116444321 - 31 -0 - 12 -443.75 - 22 --18.9592883555679 - 32 -0 - 13 -443.75 - 23 --18.9592883555679 - 33 -0 - 0 -MTEXT - 5 -E5 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -437.5 - 20 --15.3125 - 30 -0 - 40 -6.25 - 41 -7.638888888889277 - 71 - 5 - 72 - 1 - 1 -25 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -E6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -425 - 20 -23.4375 - 11 -425 - 21 --23.125 - 0 -LINE - 5 -E7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -450 - 20 -23.4375 - 11 -450 - 21 --23.125 - 0 -ENDBLK - 5 -72 -330 -70 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -74 -330 -73 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D8 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D8 - 1 - - 0 -LINE - 5 -E8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -0 - 20 -480 - 11 -450 - 21 -480 - 0 -SOLID - 5 -E9 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -0 - 20 -480 - 30 -0 - 11 -6.25 - 21 -481.0407116444321 - 31 -0 - 12 -6.25 - 22 -478.9592883555679 - 32 -0 - 13 -6.25 - 23 -478.9592883555679 - 33 -0 - 0 -SOLID - 5 -EA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -450 - 20 -480 - 30 -0 - 11 -443.75 - 21 -478.9592883555679 - 31 -0 - 12 -443.75 - 22 -481.0407116444321 - 32 -0 - 13 -443.75 - 23 -481.0407116444321 - 33 -0 - 0 -MTEXT - 5 -EB -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -225 - 20 -484.6875 - 30 -0 - 40 -6.25 - 41 -13.19444444444483 - 71 - 5 - 72 - 1 - 1 -450 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -EC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -9.567237139237322e-017 - 20 -451.5625 - 11 -1.913447427847464e-016 - 21 -483.125 - 0 -LINE - 5 -ED -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -450 - 20 -451.5625 - 11 -450 - 21 -483.125 - 0 -ENDBLK - 5 -75 -330 -73 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -77 -330 -76 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D10 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D10 - 1 - - 0 -LINE - 5 -EE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --10.00000000000002 - 20 -62.5 - 11 --10 - 21 -387.5 - 0 -SOLID - 5 -EF -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --10.00000000000002 - 20 -62.5 - 30 -0 - 11 --11.04071164443212 - 21 -68.75 - 31 -0 - 12 --8.959288355567915 - 22 -68.75 - 32 -0 - 13 --8.959288355567915 - 23 -68.75 - 33 -0 - 0 -SOLID - 5 -F0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --10 - 20 -387.5 - 30 -0 - 11 --8.959288355567899 - 21 -381.25 - 31 -0 - 12 --11.0407116444321 - 22 -381.25 - 32 -0 - 13 --11.0407116444321 - 23 -381.25 - 33 -0 - 0 -MTEXT - 5 -F1 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 --14.68750000000001 - 20 -225 - 30 -0 - 40 -6.25 - 41 -12.50000000000077 - 71 - 5 - 72 - 1 - 1 -325 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -F2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -45.9375 - 20 -62.5 - 11 --13.12500000000002 - 21 -62.5 - 0 -LINE - 5 -F3 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -45.9375 - 20 -387.5 - 11 --13.125 - 21 -387.5 - 0 -ENDBLK - 5 -78 -330 -76 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -7A -330 -79 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D15 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D15 - 1 - - 0 -LINE - 5 -F4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 --9.999999999999996 - 20 -55.00000000000001 - 11 --10 - 21 -3.463895836830489e-015 - 0 -SOLID - 5 -F5 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --9.999999999999996 - 20 -55.00000000000001 - 30 -0 - 11 --8.959288355567896 - 21 -48.75000000000001 - 31 -0 - 12 --11.0407116444321 - 22 -48.75000000000001 - 32 -0 - 13 --11.0407116444321 - 23 -48.75000000000001 - 33 -0 - 0 -SOLID - 5 -F6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --10 - 20 -3.463895836830489e-015 - 30 -0 - 11 --11.0407116444321 - 21 -6.250000000000004 - 31 -0 - 12 --8.959288355567898 - 22 -6.250000000000004 - 32 -0 - 13 --8.959288355567898 - 23 -6.250000000000004 - 33 -0 - 0 -MTEXT - 5 -F7 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 --14.6875 - 20 -27.5 - 30 -0 - 40 -6.25 - 41 -7.638888888889664 - 71 - 5 - 72 - 1 - 1 -55 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -F8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -53.4375 - 20 -55 - 11 --13.125 - 21 -55.00000000000001 - 0 -LINE - 5 -F9 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -53.4375 - 20 -1.913447427847464e-016 - 11 --13.125 - 21 -3.846585322399982e-015 - 0 -ENDBLK - 5 -7B -330 -79 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -7D -330 -7C -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D14 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D14 - 1 - - 0 -LINE - 5 -FA -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -225 - 20 -30 - 11 -47.5 - 21 -30 - 0 -SOLID - 5 -FB -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -225 - 20 -30 - 30 -0 - 11 -218.75 - 21 -28.9592883555679 - 31 -0 - 12 -218.75 - 22 -31.0407116444321 - 32 -0 - 13 -218.75 - 23 -31.0407116444321 - 33 -0 - 0 -SOLID - 5 -FC -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -47.5 - 20 -30 - 30 -0 - 11 -53.75 - 21 -31.0407116444321 - 31 -0 - 12 -53.75 - 22 -28.9592883555679 - 32 -0 - 13 -53.75 - 23 -28.9592883555679 - 33 -0 - 0 -MTEXT - 5 -FD -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -136.25 - 20 -34.6875 - 30 -0 - 40 -6.25 - 41 -18.40277777777816 - 71 - 5 - 72 - 1 - 1 -177,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -360 - 73 - 2 - 44 -1 - 0 -LINE - 5 -FE -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -225 - 20 -53.4375 - 11 -225 - 21 -26.875 - 0 -LINE - 5 -FF -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -53.4375 - 11 -47.5 - 21 -26.875 - 0 -ENDBLK - 5 -7E -330 -7C -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -80 -330 -7F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D23 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D23 - 1 - - 0 -LINE - 5 -100 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -420 - 20 -382.5 - 11 -420 - 21 -351.5 - 0 -SOLID - 5 -101 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -382.5 - 30 -0 - 11 -421.0407116444321 - 21 -376.25 - 31 -0 - 12 -418.9592883555679 - 22 -376.25 - 32 -0 - 13 -418.9592883555679 - 23 -376.25 - 33 -0 - 0 -SOLID - 5 -102 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -351.5 - 30 -0 - 11 -418.9592883555679 - 21 -357.75 - 31 -0 - 12 -421.0407116444321 - 22 -357.75 - 32 -0 - 13 -421.0407116444321 - 23 -357.75 - 33 -0 - 0 -MTEXT - 5 -103 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -415.3125 - 20 -367 - 30 -0 - 40 -6.25 - 41 -6.250000000000387 - 71 - 5 - 72 - 1 - 1 -31 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -104 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -384.0625 - 20 -382.5 - 11 -423.125 - 21 -382.5 - 0 -LINE - 5 -105 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -384.0625 - 20 -351.5 - 11 -423.125 - 21 -351.5 - 0 -ENDBLK - 5 -81 -330 -7F -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -83 -330 -82 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D2 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D2 - 1 - - 0 -LINE - 5 -106 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -365.9090909089 - 20 --30 - 11 -450 - 21 --30 - 0 -SOLID - 5 -107 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -365.9090909089 - 20 --30 - 30 -0 - 11 -372.1590909089 - 21 --28.9592883555679 - 31 -0 - 12 -372.1590909089 - 22 --31.0407116444321 - 32 -0 - 13 -372.1590909089 - 23 --31.0407116444321 - 33 -0 - 0 -SOLID - 5 -108 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -450 - 20 --30 - 30 -0 - 11 -443.75 - 21 --31.0407116444321 - 31 -0 - 12 -443.75 - 22 --28.9592883555679 - 32 -0 - 13 -443.75 - 23 --28.9592883555679 - 33 -0 - 0 -MTEXT - 5 -109 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -407.95454545445 - 20 --25.3125 - 30 -0 - 40 -6.25 - 41 -20.48611111111111 - 71 - 5 - 72 - 1 - 1 -84,09 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -10A -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -365.9090909089 - 20 -83.9375 - 11 -365.9090909089 - 21 --33.125 - 0 -LINE - 5 -10B -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -450 - 20 -83.9375 - 11 -450 - 21 --33.125 - 0 -ENDBLK - 5 -84 -330 -82 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -86 -330 -85 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D9 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D9 - 1 - - 0 -LINE - 5 -10C -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -410 - 20 -460 - 11 -435 - 21 -460 - 0 -SOLID - 5 -10D -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -410 - 20 -460 - 30 -0 - 11 -416.25 - 21 -461.0407116444321 - 31 -0 - 12 -416.25 - 22 -458.9592883555679 - 32 -0 - 13 -416.25 - 23 -458.9592883555679 - 33 -0 - 0 -SOLID - 5 -10E -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -435 - 20 -460 - 30 -0 - 11 -428.75 - 21 -458.9592883555679 - 31 -0 - 12 -428.75 - 22 -461.0407116444321 - 32 -0 - 13 -428.75 - 23 -461.0407116444321 - 33 -0 - 0 -MTEXT - 5 -10F -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -422.5 - 20 -464.6875 - 30 -0 - 40 -6.25 - 41 -7.638888888889277 - 71 - 5 - 72 - 1 - 1 -25 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -110 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -410 - 20 -416.5625 - 11 -410 - 21 -463.125 - 0 -LINE - 5 -111 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -435 - 20 -416.5625 - 11 -435 - 21 -463.125 - 0 -ENDBLK - 5 -87 -330 -85 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -89 -330 -88 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D3 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D3 - 1 - - 0 -LINE - 5 -112 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -470 - 20 -25 - 11 -470 - 21 -0 - 0 -SOLID - 5 -113 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -470 - 20 -25 - 30 -0 - 11 -471.0407116444321 - 21 -18.75 - 31 -0 - 12 -468.9592883555679 - 22 -18.75 - 32 -0 - 13 -468.9592883555679 - 23 -18.75 - 33 -0 - 0 -SOLID - 5 -114 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -470 - 20 -0 - 30 -0 - 11 -468.9592883555679 - 21 -6.25 - 31 -0 - 12 -471.0407116444321 - 22 -6.25 - 32 -0 - 13 -471.0407116444321 - 23 -6.25 - 33 -0 - 0 -MTEXT - 5 -115 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -465.3125 - 20 -12.5 - 30 -0 - 40 -6.25 - 41 -7.638888888889277 - 71 - 5 - 72 - 1 - 1 -25 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -116 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -426.5625 - 20 -25 - 11 -473.125 - 21 -25 - 0 -LINE - 5 -117 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -426.5625 - 20 -0 - 11 -473.125 - 21 -0 - 0 -ENDBLK - 5 -8A -330 -88 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -8C -330 -8B -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D24 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D24 - 1 - - 0 -LINE - 5 -118 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -420 - 20 -346.5 - 11 -420 - 21 -320.5 - 0 -SOLID - 5 -119 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -346.5 - 30 -0 - 11 -421.0407116444321 - 21 -340.25 - 31 -0 - 12 -418.9592883555679 - 22 -340.25 - 32 -0 - 13 -418.9592883555679 - 23 -340.25 - 33 -0 - 0 -SOLID - 5 -11A -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -420 - 20 -320.5 - 30 -0 - 11 -418.9592883555679 - 21 -326.75 - 31 -0 - 12 -421.0407116444321 - 22 -326.75 - 32 -0 - 13 -421.0407116444321 - 23 -326.75 - 33 -0 - 0 -MTEXT - 5 -11B -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -415.3125 - 20 -333.5 - 30 -0 - 40 -6.25 - 41 -7.638888888889277 - 71 - 5 - 72 - 1 - 1 -26 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -11C -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -384.0625 - 20 -346.5 - 11 -423.125 - 21 -346.5 - 0 -LINE - 5 -11D -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -384.0625 - 20 -320.5 - 11 -423.125 - 21 -320.5 - 0 -ENDBLK - 5 -8D -330 -8B -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -8F -330 -8E -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D11 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D11 - 1 - - 0 -LINE - 5 -11E -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -460 - 11 --3.944304526105059e-031 - 21 -460 - 0 -SOLID - 5 -11F -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -47.5 - 20 -460 - 30 -0 - 11 -41.25 - 21 -458.9592883555679 - 31 -0 - 12 -41.25 - 22 -461.0407116444321 - 32 -0 - 13 -41.25 - 23 -461.0407116444321 - 33 -0 - 0 -SOLID - 5 -120 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 --3.944304526105059e-031 - 20 -460 - 30 -0 - 11 -6.25 - 21 -461.0407116444321 - 31 -0 - 12 -6.25 - 22 -458.9592883555679 - 32 -0 - 13 -6.25 - 23 -458.9592883555679 - 33 -0 - 0 -MTEXT - 5 -121 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -23.75 - 20 -464.6875 - 30 -0 - 40 -6.25 - 41 -15.62500000000039 - 71 - 5 - 72 - 1 - 1 -47,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -360 - 73 - 2 - 44 -1 - 0 -LINE - 5 -122 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -47.5 - 20 -404.0625 - 11 -47.5 - 21 -463.125 - 0 -LINE - 5 -123 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -9.567237139237322e-017 - 20 -404.0625 - 11 -1.913447427847461e-016 - 21 -463.125 - 0 -ENDBLK - 5 -90 -330 -8E -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -92 -330 -91 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D16 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D16 - 1 - - 0 -LINE - 5 -124 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -29.99999999999999 - 20 -62.5 - 11 -30 - 21 -225 - 0 -SOLID - 5 -125 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -29.99999999999999 - 20 -62.5 - 30 -0 - 11 -28.95928835556789 - 21 -68.75 - 31 -0 - 12 -31.04071164443209 - 22 -68.75 - 32 -0 - 13 -31.04071164443209 - 23 -68.75 - 33 -0 - 0 -SOLID - 5 -126 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -30 - 20 -225 - 30 -0 - 11 -31.0407116444321 - 21 -218.75 - 31 -0 - 12 -28.9592883555679 - 22 -218.75 - 32 -0 - 13 -28.9592883555679 - 23 -218.75 - 33 -0 - 0 -MTEXT - 5 -127 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -25.31249999999999 - 20 -143.75 - 30 -0 - 40 -6.25 - 41 -18.40277777777855 - 71 - 5 - 72 - 1 - 1 -162,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -90 - 73 - 2 - 44 -1 - 0 -LINE - 5 -128 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -53.4375 - 20 -62.5 - 11 -26.87499999999999 - 21 -62.5 - 0 -LINE - 5 -129 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -53.4375 - 20 -225 - 11 -26.875 - 21 -225 - 0 -ENDBLK - 5 -93 -330 -91 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -95 -330 -94 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D22 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D22 - 1 - - 0 -LINE - 5 -12A -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -98.18181818180001 - 20 -412.5 - 11 -126.3636363636 - 21 -412.5 - 0 -SOLID - 5 -12B -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -98.18181818180001 - 20 -412.5 - 30 -0 - 11 -104.4318181818 - 21 -413.5407116444321 - 31 -0 - 12 -104.4318181818 - 22 -411.4592883555679 - 32 -0 - 13 -104.4318181818 - 23 -411.4592883555679 - 33 -0 - 0 -SOLID - 5 -12C -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -126.3636363636 - 20 -412.5 - 30 -0 - 11 -120.1136363636 - 21 -411.4592883555679 - 31 -0 - 12 -120.1136363636 - 22 -413.5407116444321 - 32 -0 - 13 -120.1136363636 - 23 -413.5407116444321 - 33 -0 - 0 -MTEXT - 5 -12D -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -112.2727272727 - 20 -417.1875 - 30 -0 - 40 -6.25 - 41 -18.40277777777778 - 71 - 5 - 72 - 1 - 1 -28,18 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -12E -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -98.18181818180001 - 20 -389.0625 - 11 -98.18181818180001 - 21 -415.625 - 0 -LINE - 5 -12F -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -126.3636363636 - 20 -389.0625 - 11 -126.3636363636 - 21 -415.625 - 0 -ENDBLK - 5 -96 -330 -94 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -98 -330 -97 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D18 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D18 - 1 - - 0 -LINE - 5 -130 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -337.7272727270999 - 20 -30 - 11 -365.9090909089 - 21 -30 - 0 -SOLID - 5 -131 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -337.7272727270999 - 20 -30 - 30 -0 - 11 -343.9772727270999 - 21 -31.0407116444321 - 31 -0 - 12 -343.9772727270999 - 22 -28.9592883555679 - 32 -0 - 13 -343.9772727270999 - 23 -28.9592883555679 - 33 -0 - 0 -SOLID - 5 -132 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -365.9090909089 - 20 -30 - 30 -0 - 11 -359.6590909089 - 21 -28.9592883555679 - 31 -0 - 12 -359.6590909089 - 22 -31.0407116444321 - 32 -0 - 13 -359.6590909089 - 23 -31.0407116444321 - 33 -0 - 0 -MTEXT - 5 -133 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -351.818181818 - 20 -34.6875 - 30 -0 - 40 -6.25 - 41 -18.40277777777778 - 71 - 5 - 72 - 1 - 1 -28,18 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -134 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -337.7272727270999 - 20 -83.9375 - 11 -337.7272727270999 - 21 -26.875 - 0 -LINE - 5 -135 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -365.9090909089 - 20 -83.9375 - 11 -365.9090909089 - 21 -26.875 - 0 -ENDBLK - 5 -99 -330 -97 -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -9B -330 -9A -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D21 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D21 - 1 - - 0 -LINE - 5 -136 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -62.49999999999999 - 20 -412.5 - 11 -98.18181818180001 - 21 -412.5 - 0 -SOLID - 5 -137 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -62.49999999999999 - 20 -412.5 - 30 -0 - 11 -68.75 - 21 -413.5407116444321 - 31 -0 - 12 -68.75 - 22 -411.4592883555679 - 32 -0 - 13 -68.75 - 23 -411.4592883555679 - 33 -0 - 0 -SOLID - 5 -138 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -98.18181818180001 - 20 -412.5 - 30 -0 - 11 -91.93181818180001 - 21 -411.4592883555679 - 31 -0 - 12 -91.93181818180001 - 22 -413.5407116444321 - 32 -0 - 13 -91.93181818180001 - 23 -413.5407116444321 - 33 -0 - 0 -MTEXT - 5 -139 -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -80.3409090909 - 20 -417.1875 - 30 -0 - 40 -6.25 - 41 -19.79166666666783 - 71 - 5 - 72 - 1 - 1 -35,68 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -13A -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -62.5 - 20 -389.0625 - 11 -62.49999999999999 - 21 -415.625 - 0 -LINE - 5 -13B -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -98.18181818180001 - 20 -389.0625 - 11 -98.18181818180001 - 21 -415.625 - 0 -ENDBLK - 5 -9C -330 -9A -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -BLOCK - 5 -9E -330 -9D -100 -AcDbEntity - 8 -0 -100 -AcDbBlockBegin - 2 -*D26 - 70 - 1 - 10 -0 - 20 -0 - 3 -*D26 - 1 - - 0 -LINE - 5 -13C -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -352 - 20 -410 - 11 -402.5 - 21 -410 - 0 -SOLID - 5 -13D -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -352 - 20 -410 - 30 -0 - 11 -358.25 - 21 -411.0407116444321 - 31 -0 - 12 -358.25 - 22 -408.9592883555679 - 32 -0 - 13 -358.25 - 23 -408.9592883555679 - 33 -0 - 0 -SOLID - 5 -13E -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbTrace - 10 -402.5 - 20 -410 - 30 -0 - 11 -396.25 - 21 -408.9592883555679 - 31 -0 - 12 -396.25 - 22 -411.0407116444321 - 32 -0 - 13 -396.25 - 23 -411.0407116444321 - 33 -0 - 0 -MTEXT - 5 -13F -100 -AcDbEntity - 8 -Dimensions - 6 -CONTINUOUS - 62 - 0 -370 - -2 -100 -AcDbMText - 10 -377.25 - 20 -414.6875 - 30 -0 - 40 -6.25 - 41 -14.93055555555633 - 71 - 5 - 72 - 1 - 1 -50,5 - 7 -STANDARD -210 -0 -220 -0 -230 -1 - 50 -0 - 73 - 2 - 44 -1 - 0 -LINE - 5 -140 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -352 - 20 -396.5625 - 11 -352 - 21 -413.125 - 0 -LINE - 5 -141 -100 -AcDbEntity - 8 -Dimensions - 6 -ByBlock - 62 - 0 -370 - -2 -100 -AcDbLine - 10 -402.5 - 20 -396.5625 - 11 -402.5 - 21 -413.125 - 0 -ENDBLK - 5 -9F -330 -9D -100 -AcDbEntity - 8 -0 -100 -AcDbBlockEnd - 0 -ENDSEC - 0 -SECTION - 2 -ENTITIES - 0 -LINE - 5 -142 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -0 - 20 -0 - 11 -0 - 21 -450 - 0 -LINE - 5 -143 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -0 - 20 -450 - 11 -450 - 21 -450 - 0 -LINE - 5 -144 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -450 - 20 -450 - 11 -450 - 21 -0 - 0 -LINE - 5 -145 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -450 - 20 -0 - 11 -0 - 21 -0 - 0 -LINE - 5 -146 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -15 - 20 -435 - 11 -15 - 21 -15 - 0 -LINE - 5 -147 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -435 - 20 -435 - 11 -435 - 21 -15 - 0 -CIRCLE - 5 -148 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -55 - 20 -395 - 40 -5 - 0 -CIRCLE - 5 -149 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -395 - 40 -5 - 0 -CIRCLE - 5 -14A -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -395 - 20 -395 - 40 -5 - 0 -CIRCLE - 5 -14B -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -55 - 20 -225 - 40 -5 - 0 -CIRCLE - 5 -14C -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -395 - 20 -225 - 40 -5 - 0 -CIRCLE - 5 -14D -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -55 - 20 -55 - 40 -5 - 0 -CIRCLE - 5 -14E -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -55 - 40 -5 - 0 -CIRCLE - 5 -14F -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -395 - 20 -55 - 40 -5 - 0 -CIRCLE - 5 -150 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -25 - 20 -425 - 40 -2.5 - 0 -CIRCLE - 5 -151 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -425 - 20 -425 - 40 -2.5 - 0 -CIRCLE - 5 -152 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -25 - 20 -25 - 40 -2.5 - 0 -CIRCLE - 5 -153 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -425 - 20 -25 - 40 -2.5 - 0 -CIRCLE - 5 -154 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -155 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -156 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -157 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -158 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -159 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15A -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15B -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15C -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15D -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15E -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -85.5 - 40 -2.5 - 0 -CIRCLE - 5 -15F -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -160 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -161 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -162 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -163 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -164 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -165 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -166 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -167 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -168 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -169 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -116.5 - 40 -2.5 - 0 -CIRCLE - 5 -16A -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -16B -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -16C -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -16D -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -16E -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -16F -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -170 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -171 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -172 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -173 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -174 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -147.5 - 40 -2.5 - 0 -CIRCLE - 5 -175 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -176 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -177 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -178 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -179 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17A -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17B -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17C -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17D -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17E -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -17F -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -178.5 - 40 -2.5 - 0 -CIRCLE - 5 -180 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -181 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -182 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -183 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -184 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -185 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -186 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -187 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -188 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -189 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -18A -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -209.5 - 40 -2.5 - 0 -CIRCLE - 5 -18B -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -18C -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -18D -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -18E -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -18F -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -190 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -191 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -192 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -193 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -194 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -195 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -240.5 - 40 -2.5 - 0 -CIRCLE - 5 -196 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -197 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -198 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -199 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19A -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19B -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19C -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19D -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19E -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -19F -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A0 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -271.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A1 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A2 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A3 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A4 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A5 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A6 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A7 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A8 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1A9 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AA -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AB -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -302.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AC -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AD -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AE -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1AF -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B0 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B1 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B2 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B3 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B4 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B5 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B6 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -333.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B7 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -365.9090909089 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B8 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -337.7272727270999 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1B9 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -309.5454545453001 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BA -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -281.3636363635 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BB -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -253.1818181817 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BC -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -225 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BD -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -196.8181818181 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BE -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -168.6363636363 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1BF -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -140.4545454545 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1C0 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -112.2727272727 - 20 -364.5 - 40 -2.5 - 0 -CIRCLE - 5 -1C1 -100 -AcDbEntity - 8 -LEDs - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -84.0909090909 - 20 -364.5 - 40 -2.5 - 0 -LINE - 5 -1C2 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -402.5 - 20 -62.5 - 11 -402.5 - 21 -47.5 - 0 -LINE - 5 -1C3 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -402.5 - 20 -47.5 - 11 -47.5 - 21 -47.5 - 0 -LINE - 5 -1C4 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -47.5 - 20 -47.5 - 11 -47.5 - 21 -62.5 - 0 -LINE - 5 -1C5 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -47.5 - 20 -62.5 - 11 -402.5 - 21 -62.5 - 0 -LINE - 5 -1C6 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -47.5 - 20 -402.5 - 11 -402.5 - 21 -402.5 - 0 -LINE - 5 -1C7 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -402.5 - 20 -402.5 - 11 -402.5 - 21 -387.5 - 0 -LINE - 5 -1C8 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -402.5 - 20 -387.5 - 11 -47.5 - 21 -387.5 - 0 -LINE - 5 -1C9 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -47.5 - 20 -387.5 - 11 -47.5 - 21 -402.5 - 0 -DIMENSION - 5 -1CA -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D1 - 10 -450 - 20 --20 - 30 -0 - 11 -437.5 - 21 --15.3125 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -425 - 23 -25 - 33 -0 - 14 -450 - 24 -25 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1CB -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D2 - 10 -450 - 20 --30 - 30 -0 - 11 -407.95454545445 - 21 --25.3125 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -365.9090909089 - 23 -85.5 - 33 -0 - 14 -450 - 24 -85.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1CC -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D3 - 10 -470 - 20 --5.510728592200698e-015 - 30 -0 - 11 -465.3125 - 21 -12.5 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -425 - 23 -25 - 33 -0 - 14 -425 - 24 --0 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1CD -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D4 - 10 -480 - 20 --1.397164521863323e-014 - 30 -0 - 11 -475.3125 - 21 -42.75000000000001 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -365.9090909089 - 23 -85.5 - 33 -0 - 14 -365.9090909089 - 24 -0 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -LINE - 5 -1CE -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -410 - 20 -435 - 11 -410 - 21 -410 - 0 -LINE - 5 -1CF -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -415 - 20 -435 - 11 -415 - 21 -415 - 0 -LINE - 5 -1D0 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -410 - 20 -415 - 11 -435 - 21 -415 - 0 -LINE - 5 -1D1 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -410 - 20 -410 - 11 -435 - 21 -410 - 0 -LINE - 5 -1D2 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -47.5 - 20 -387.5 - 11 -47.5 - 21 -62.5 - 0 -LINE - 5 -1D3 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -62.5 - 20 -387.5 - 11 -62.5 - 21 -62.49999999999999 - 0 -LINE - 5 -1D4 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -402.5 - 20 -387.5 - 11 -402.5 - 21 -62.5 - 0 -LINE - 5 -1D5 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -387.5 - 20 -387.5 - 11 -387.5 - 21 -62.50000000000001 - 0 -DIMENSION - 5 -1D6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D5 - 10 --4.592273826833915e-015 - 20 --20 - 30 -0 - 11 -27.5 - 21 --15.3125 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -55 - 23 -55 - 33 -0 - 14 -0 - 24 -55 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1D7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D6 - 10 --5.204577003745103e-015 - 20 --30 - 30 -0 - 11 -112.5 - 21 --25.3125 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -225 - 23 -55 - 33 -0 - 14 -0 - 24 -55 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1D8 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D7 - 10 -402.5 - 20 -460 - 30 -0 - 11 -225 - 21 -464.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -47.5 - 23 -402.5 - 33 -0 - 14 -402.5 - 24 -402.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1D9 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D8 - 10 -450 - 20 -480 - 30 -0 - 11 -225 - 21 -484.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -0 - 23 -450 - 33 -0 - 14 -450 - 24 -450 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DA -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D9 - 10 -435 - 20 -460 - 30 -0 - 11 -422.5 - 21 -464.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -410 - 23 -415 - 33 -0 - 14 -435 - 24 -415 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DB -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D10 - 10 --10 - 20 -387.5 - 30 -0 - 11 --14.68750000000001 - 21 -225 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -47.5 - 23 -62.5 - 33 -0 - 14 -47.5 - 24 -387.5 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DC -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D11 - 10 -3.520743267239335e-015 - 20 -460 - 30 -0 - 11 -23.75 - 21 -464.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -47.5 - 23 -402.5 - 33 -0 - 14 -0 - 24 -402.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DD -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D12 - 10 --10.00000000000001 - 20 -450 - 30 -0 - 11 --14.68750000000001 - 21 -426.25 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -47.82193029137293 - 23 -402.5 - 33 -0 - 14 -47.82193029137293 - 24 -450 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DE -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D13 - 10 -47.5 - 20 -30 - 30 -0 - 11 -51.25 - 21 -34.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -55 - 23 -55 - 33 -0 - 14 -47.5 - 24 -55 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1DF -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D14 - 10 -47.5 - 20 -30 - 30 -0 - 11 -136.25 - 21 -34.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -225 - 23 -55 - 33 -0 - 14 -47.5 - 24 -55 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E0 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D15 - 10 --10 - 20 -7.959941299845452e-015 - 30 -0 - 11 --14.6875 - 21 -27.5 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -55 - 23 -55 - 33 -0 - 14 -55 - 24 -0 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E1 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D16 - 10 -30 - 20 -225 - 30 -0 - 11 -25.31249999999999 - 21 -143.75 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -55 - 23 -62.5 - 33 -0 - 14 -55 - 24 -225 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E2 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D17 - 10 -420 - 20 -85.49999999999999 - 30 -0 - 11 -415.3125 - 21 -101 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -365.9090909089 - 23 -116.5 - 33 -0 - 14 -365.9090909089 - 24 -85.5 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E3 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D18 - 10 -365.9090909089 - 20 -30 - 30 -0 - 11 -351.818181818 - 21 -34.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -337.7272727270999 - 23 -85.5 - 33 -0 - 14 -365.9090909089 - 24 -85.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E4 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D19 - 10 -40 - 20 -349 - 30 -0 - 11 -35.3125 - 21 -368.25 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -62.5 - 23 -387.5 - 33 -0 - 14 -62.5 - 24 -349 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E5 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D20 - 10 -40 - 20 -318 - 30 -0 - 11 -35.3125 - 21 -333.5 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -62.5 - 23 -349 - 33 -0 - 14 -62.5 - 24 -318 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E6 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D21 - 10 -98.18181818180001 - 20 -412.5 - 30 -0 - 11 -80.3409090909 - 21 -417.1875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -62.5 - 23 -387.5 - 33 -0 - 14 -98.18181818180001 - 24 -387.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -1E7 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D22 - 10 -126.3636363636 - 20 -412.5 - 30 -0 - 11 -112.2727272727 - 21 -417.1875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -98.18181818180001 - 23 -387.5 - 33 -0 - 14 -126.3636363636 - 24 -387.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -LINE - 5 -1E8 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -382.5 - 20 -387.5 - 11 -382.5 - 21 -62.50000000000001 - 0 -LINE - 5 -1E9 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -387.5 - 11 -67.5 - 21 -62.49999999999999 - 0 -LINE - 5 -1EA -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -382.5 - 20 -382.5 - 11 -67.5 - 21 -382.5 - 0 -LINE - 5 -1EB -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -67.5 - 11 -382.5 - 21 -67.5 - 0 -LINE - 5 -1EC -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -95.68181818180001 - 20 -67.5 - 11 -95.68181818180001 - 21 -382.5 - 0 -LINE - 5 -1ED -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -100.6818181818 - 20 -67.5 - 11 -100.6818181818 - 21 -382.5 - 0 -LINE - 5 -1EE -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -123.8636363636 - 20 -67.5 - 11 -123.8636363636 - 21 -382.5 - 0 -LINE - 5 -1EF -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -128.8636363636 - 20 -67.5 - 11 -128.8636363636 - 21 -382.5 - 0 -LINE - 5 -1F0 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -152.0454545454 - 20 -67.5 - 11 -152.0454545454 - 21 -382.5 - 0 -LINE - 5 -1F1 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -157.0454545454 - 20 -67.5 - 11 -157.0454545454 - 21 -382.5 - 0 -LINE - 5 -1F2 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -180.2272727272 - 20 -67.5 - 11 -180.2272727272 - 21 -382.5 - 0 -LINE - 5 -1F3 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -185.2272727272 - 20 -67.5 - 11 -185.2272727272 - 21 -382.5 - 0 -LINE - 5 -1F4 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -208.409090909 - 20 -67.5 - 11 -208.409090909 - 21 -382.5 - 0 -LINE - 5 -1F5 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -213.409090909 - 20 -67.5 - 11 -213.409090909 - 21 -382.5 - 0 -LINE - 5 -1F6 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -236.5909090908 - 20 -67.5 - 11 -236.5909090908 - 21 -382.5 - 0 -LINE - 5 -1F7 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -241.5909090908 - 20 -67.5 - 11 -241.5909090908 - 21 -382.5 - 0 -LINE - 5 -1F8 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -264.7727272726 - 20 -67.5 - 11 -264.7727272726 - 21 -382.5 - 0 -LINE - 5 -1F9 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -269.7727272726 - 20 -67.5 - 11 -269.7727272726 - 21 -382.5 - 0 -LINE - 5 -1FA -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -292.9545454544 - 20 -67.5 - 11 -292.9545454544 - 21 -382.5 - 0 -LINE - 5 -1FB -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -297.9545454544 - 20 -67.5 - 11 -297.9545454544 - 21 -382.5 - 0 -LINE - 5 -1FC -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -321.1363636362 - 20 -67.5 - 11 -321.1363636362 - 21 -382.5 - 0 -LINE - 5 -1FD -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -326.1363636362 - 20 -67.5 - 11 -326.1363636362 - 21 -382.5 - 0 -LINE - 5 -1FE -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -349.3181818179999 - 20 -67.5 - 11 -349.3181818179999 - 21 -382.5 - 0 -LINE - 5 -1FF -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -354.3181818179999 - 20 -67.5 - 11 -354.3181818179999 - 21 -382.5 - 0 -LINE - 5 -200 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -351.5 - 11 -382.5 - 21 -351.5 - 0 -LINE - 5 -201 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -346.5 - 11 -382.5 - 21 -346.5 - 0 -LINE - 5 -202 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -320.5 - 11 -382.5 - 21 -320.5 - 0 -LINE - 5 -203 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -315.5 - 11 -382.5 - 21 -315.5 - 0 -LINE - 5 -204 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -289.5 - 11 -382.5 - 21 -289.5 - 0 -LINE - 5 -205 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -284.5 - 11 -382.5 - 21 -284.5 - 0 -LINE - 5 -206 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -258.5 - 11 -382.5 - 21 -258.5 - 0 -LINE - 5 -207 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -253.5 - 11 -382.5 - 21 -253.5 - 0 -LINE - 5 -208 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -227.5 - 11 -382.5 - 21 -227.5 - 0 -LINE - 5 -209 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -222.5 - 11 -382.5 - 21 -222.5 - 0 -LINE - 5 -20A -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -196.5 - 11 -382.5 - 21 -196.5 - 0 -LINE - 5 -20B -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -191.5 - 11 -382.5 - 21 -191.5 - 0 -LINE - 5 -20C -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -165.5 - 11 -382.5 - 21 -165.5 - 0 -LINE - 5 -20D -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -160.5 - 11 -382.5 - 21 -160.5 - 0 -LINE - 5 -20E -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -134.5 - 11 -382.5 - 21 -134.5 - 0 -LINE - 5 -20F -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -129.5 - 11 -382.5 - 21 -129.5 - 0 -LINE - 5 -210 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -103.5 - 11 -382.5 - 21 -103.5 - 0 -LINE - 5 -211 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -67.5 - 20 -98.5 - 11 -382.5 - 21 -98.5 - 0 -DIMENSION - 5 -212 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D23 - 10 -420 - 20 -351.5 - 30 -0 - 11 -415.3125 - 21 -367 - 31 -0 - 70 - 32 - 71 - 5 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -382.5 - 23 -382.5 - 33 -0 - 14 -382.5 - 24 -351.5 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -213 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D24 - 10 -420 - 20 -320.5 - 30 -0 - 11 -415.3125 - 21 -333.5 - 31 -0 - 70 - 32 - 71 - 5 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -382.5 - 23 -346.5 - 33 -0 - 14 -382.5 - 24 -320.5 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -214 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D25 - 10 --30 - 20 -15 - 30 -0 - 11 --34.68749999999999 - 21 -225 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -0 - 23 -435 - 33 -0 - 14 -0 - 24 -15 - 34 -0 - 50 -90 -100 -AcDbRotatedDimension - 0 -CIRCLE - 5 -215 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -98 - 20 -396 - 40 -1 - 0 -CIRCLE - 5 -216 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbCircle - 10 -352 - 20 -395 - 40 -1 - 0 -DIMENSION - 5 -217 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D26 - 10 -402.5 - 20 -410 - 30 -0 - 11 -377.25 - 21 -414.6875 - 31 -0 - 70 - 32 - 71 - 5 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -352 - 23 -395 - 33 -0 - 14 -402.5 - 24 -395 - 34 -0 -100 -AcDbRotatedDimension - 0 -DIMENSION - 5 -218 -100 -AcDbEntity - 8 -Dimensions - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbDimension - 2 -*D27 - 10 -152.0454545454 - 20 -413 - 30 -0 - 11 -140.4545454545 - 21 -417.6875 - 31 -0 - 70 - 32 - 71 - 5 - 72 - 0 - 3 -Standard - 53 -0 -210 -0 -220 -0 -230 -1 -100 -AcDbAlignedDimension - 13 -128.8636363636 - 23 -382.5 - 33 -0 - 14 -152.0454545454 - 24 -382.5 - 34 -0 -100 -AcDbRotatedDimension - 0 -LINE - 5 -219 -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -15 - 20 -435 - 11 -435 - 21 -435 - 0 -LINE - 5 -21A -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -15 - 20 -15 - 11 -435 - 21 -15 - 0 -LINE - 5 -21B -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -15 - 20 -15 - 11 -0 - 21 -0 - 0 -LINE - 5 -21C -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -15 - 20 -435 - 11 -0 - 21 -450 - 0 -LINE - 5 -21D -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -435 - 20 -435 - 11 -450 - 21 -450 - 0 -LINE - 5 -21E -100 -AcDbEntity - 8 -0 - 6 -ByLayer - 62 - 256 -370 - -1 -100 -AcDbLine - 10 -435 - 20 -15 - 11 -450 - 21 -0 - 0 -ENDSEC - 0 -SECTION - 2 -OBJECTS - 0 -DICTIONARY - 5 -C -330 -0 -100 -AcDbDictionary -281 - 1 - 3 -ACAD_GROUP -350 -D - 0 -DICTIONARY - 5 -D -330 -C -100 -AcDbDictionary -281 - 1 - 0 -ENDSEC - 0 -EOF +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$EXTMIN + 10 +-37.81250000000001 + 20 +-33.125 + 30 +0 + 9 +$EXTMAX + 10 +483.125 + 20 +487.8125 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +420 + 20 +297 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1 + 9 +$ATTMODE + 70 + 0 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +15.68 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +2.5 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 +STANDARD + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7854 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1 + 9 +$FILLETRAD + 40 +0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 34 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 2 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +12.5 + 20 +56 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +0 + 20 +0 + 30 +0 + 9 +$PEXTMAX + 10 +0 + 20 +0 + 30 +0 + 9 +$GRIDMODE + 70 + 1 + 9 +$SNAPSTYLE + 70 + 0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +210 + 20 +297 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0.4111115222226333 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +50 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +5 + 9 +$PSOLHEIGHT + 40 +80 + 9 +$LOFTANG1 + 40 +1.570796326794897 + 9 +$LOFTANG2 + 40 +1.570796326794897 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +1 + 9 +$LONGITUDE + 40 +1 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 1 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +362.5794227574751 + 22 +245.46944213732 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +526.7064645625692 + 41 +1.907995618838992 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.62 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Dimensions + 70 + 0 + 62 + 136 +420 +32896 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +LEDs + 70 + 0 + 62 + 2 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +4C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +4D +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +4E +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +2.5 + 41 +2.5 + 42 +0.625 + 43 +0.38 + 44 +1.25 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +2.5 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +0.625 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 8 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +179 + 0 +271 + 2 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 44 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +STANDARD +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +4F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D13 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +52 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D19 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +55 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D17 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +58 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +5B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D27 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +5E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +61 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D12 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +64 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D25 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +67 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +6A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D20 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +6D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +70 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D1 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +73 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +76 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +79 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D15 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +7C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D14 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +7F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D23 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +82 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +85 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D9 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +88 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +8B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D24 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +8E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D11 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +91 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D16 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +94 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D22 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +97 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D18 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +9A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D21 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +9D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D26 + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +50 +330 +4F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D13 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D13 + 1 + + 0 +LINE + 5 +A0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +67.5 + 20 +30 + 11 +35 + 21 +30 + 0 +SOLID + 5 +A1 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +55 + 20 +30 + 30 +0 + 11 +61.25 + 21 +31.0407116444321 + 31 +0 + 12 +61.25 + 22 +28.9592883555679 + 32 +0 + 13 +61.25 + 23 +28.9592883555679 + 33 +0 + 0 +SOLID + 5 +A2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +47.5 + 20 +30 + 30 +0 + 11 +41.25 + 21 +28.9592883555679 + 31 +0 + 12 +41.25 + 22 +31.0407116444321 + 32 +0 + 13 +41.25 + 23 +31.0407116444321 + 33 +0 + 0 +MTEXT + 5 +A3 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +61.59722222222241 + 20 +34.6875 + 30 +0 + 40 +6.25 + 41 +10.06944444444483 + 71 + 5 + 72 + 1 + 1 +7,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +360 + 73 + 2 + 44 +1 + 0 +LINE + 5 +A4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +55 + 20 +53.4375 + 11 +55 + 21 +26.875 + 0 +LINE + 5 +A5 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +53.4375 + 11 +47.5 + 21 +26.875 + 0 +ENDBLK + 5 +51 +330 +4F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +53 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D19 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D19 + 1 + + 0 +LINE + 5 +A6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +40 + 20 +387.5 + 11 +40 + 21 +349 + 0 +SOLID + 5 +A7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +40 + 20 +387.5 + 30 +0 + 11 +41.0407116444321 + 21 +381.25 + 31 +0 + 12 +38.9592883555679 + 22 +381.25 + 32 +0 + 13 +38.9592883555679 + 23 +381.25 + 33 +0 + 0 +SOLID + 5 +A8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +40 + 20 +349 + 30 +0 + 11 +38.9592883555679 + 21 +355.25 + 31 +0 + 12 +41.0407116444321 + 22 +355.25 + 32 +0 + 13 +41.0407116444321 + 23 +355.25 + 33 +0 + 0 +MTEXT + 5 +A9 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +35.3125 + 20 +368.25 + 30 +0 + 40 +6.25 + 41 +14.93055555555633 + 71 + 5 + 72 + 1 + 1 +38,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +AA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +60.9375 + 20 +387.5 + 11 +36.875 + 21 +387.5 + 0 +LINE + 5 +AB +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +60.9375 + 20 +349 + 11 +36.875 + 21 +349 + 0 +ENDBLK + 5 +54 +330 +52 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +56 +330 +55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D17 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D17 + 1 + + 0 +LINE + 5 +AC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +420 + 20 +116.5 + 11 +420 + 21 +85.5 + 0 +SOLID + 5 +AD +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +116.5 + 30 +0 + 11 +421.0407116444321 + 21 +110.25 + 31 +0 + 12 +418.9592883555679 + 22 +110.25 + 32 +0 + 13 +418.9592883555679 + 23 +110.25 + 33 +0 + 0 +SOLID + 5 +AE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +85.5 + 30 +0 + 11 +418.9592883555679 + 21 +91.75 + 31 +0 + 12 +421.0407116444321 + 22 +91.75 + 32 +0 + 13 +421.0407116444321 + 23 +91.75 + 33 +0 + 0 +MTEXT + 5 +AF +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +415.3125 + 20 +101 + 30 +0 + 40 +6.25 + 41 +6.250000000000387 + 71 + 5 + 72 + 1 + 1 +31 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +B0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +367.4715909089 + 20 +116.5 + 11 +423.125 + 21 +116.5 + 0 +LINE + 5 +B1 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +367.4715909089 + 20 +85.5 + 11 +423.125 + 21 +85.5 + 0 +ENDBLK + 5 +57 +330 +55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +59 +330 +58 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D5 + 1 + + 0 +LINE + 5 +B2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +55.00000000000001 + 20 +-20 + 11 +0 + 21 +-20 + 0 +SOLID + 5 +B3 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +55.00000000000001 + 20 +-20 + 30 +0 + 11 +48.75000000000001 + 21 +-21.0407116444321 + 31 +0 + 12 +48.75000000000001 + 22 +-18.9592883555679 + 32 +0 + 13 +48.75000000000001 + 23 +-18.9592883555679 + 33 +0 + 0 +SOLID + 5 +B4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +0 + 20 +-20 + 30 +0 + 11 +6.25 + 21 +-18.9592883555679 + 31 +0 + 12 +6.25 + 22 +-21.0407116444321 + 32 +0 + 13 +6.25 + 23 +-21.0407116444321 + 33 +0 + 0 +MTEXT + 5 +B5 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +27.5 + 20 +-15.3125 + 30 +0 + 40 +6.25 + 41 +7.638888888889664 + 71 + 5 + 72 + 1 + 1 +55 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +360 + 73 + 2 + 44 +1 + 0 +LINE + 5 +B6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +55 + 20 +53.4375 + 11 +55.00000000000001 + 21 +-23.125 + 0 +LINE + 5 +B7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-2.870171141771197e-016 + 20 +53.4375 + 11 +-5.740342283542393e-016 + 21 +-23.125 + 0 +ENDBLK + 5 +5A +330 +58 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5C +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D27 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D27 + 1 + + 0 +LINE + 5 +B8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +128.8636363636 + 20 +413 + 11 +152.0454545454 + 21 +413 + 0 +SOLID + 5 +B9 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +128.8636363636 + 20 +413 + 30 +0 + 11 +135.1136363636 + 21 +414.0407116444321 + 31 +0 + 12 +135.1136363636 + 22 +411.9592883555679 + 32 +0 + 13 +135.1136363636 + 23 +411.9592883555679 + 33 +0 + 0 +SOLID + 5 +BA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +152.0454545454 + 20 +413 + 30 +0 + 11 +145.7954545454 + 21 +411.9592883555679 + 31 +0 + 12 +145.7954545454 + 22 +414.0407116444321 + 32 +0 + 13 +145.7954545454 + 23 +414.0407116444321 + 33 +0 + 0 +MTEXT + 5 +BB +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +140.4545454545 + 20 +417.6875 + 30 +0 + 40 +6.25 + 41 +18.40277777777817 + 71 + 5 + 72 + 1 + 1 +23,18 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +BC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +128.8636363636 + 20 +384.0625 + 11 +128.8636363636 + 21 +416.125 + 0 +LINE + 5 +BD +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +152.0454545454 + 20 +384.0625 + 11 +152.0454545454 + 21 +416.125 + 0 +ENDBLK + 5 +5D +330 +5B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5F +330 +5E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D4 + 1 + + 0 +LINE + 5 +BE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +480 + 20 +85.50000000000001 + 11 +480 + 21 +0 + 0 +SOLID + 5 +BF +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +480 + 20 +85.50000000000001 + 30 +0 + 11 +481.0407116444321 + 21 +79.25000000000001 + 31 +0 + 12 +478.9592883555679 + 22 +79.25000000000001 + 32 +0 + 13 +478.9592883555679 + 23 +79.25000000000001 + 33 +0 + 0 +SOLID + 5 +C0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +480 + 20 +0 + 30 +0 + 11 +478.9592883555679 + 21 +6.25 + 31 +0 + 12 +481.0407116444321 + 22 +6.25 + 32 +0 + 13 +481.0407116444321 + 23 +6.25 + 33 +0 + 0 +MTEXT + 5 +C1 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +475.3125 + 20 +42.75000000000001 + 30 +0 + 40 +6.25 + 41 +14.93055555555633 + 71 + 5 + 72 + 1 + 1 +85,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +C2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +367.4715909089 + 20 +85.5 + 11 +483.125 + 21 +85.50000000000001 + 0 +LINE + 5 +C3 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +367.4715909089 + 20 +0 + 11 +483.125 + 21 +0 + 0 +ENDBLK + 5 +60 +330 +5E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +62 +330 +61 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D12 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D12 + 1 + + 0 +LINE + 5 +C4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-10.00000000000001 + 20 +402.5 + 11 +-10.00000000000001 + 21 +450 + 0 +SOLID + 5 +C5 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-10.00000000000001 + 20 +402.5 + 30 +0 + 11 +-11.04071164443211 + 21 +408.75 + 31 +0 + 12 +-8.95928835556791 + 22 +408.75 + 32 +0 + 13 +-8.95928835556791 + 23 +408.75 + 33 +0 + 0 +SOLID + 5 +C6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-10.00000000000001 + 20 +450 + 30 +0 + 11 +-8.95928835556791 + 21 +443.75 + 31 +0 + 12 +-11.04071164443211 + 22 +443.75 + 32 +0 + 13 +-11.04071164443211 + 23 +443.75 + 33 +0 + 0 +MTEXT + 5 +C7 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +-14.68750000000001 + 20 +426.25 + 30 +0 + 40 +6.25 + 41 +15.62500000000039 + 71 + 5 + 72 + 1 + 1 +47,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +C8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +46.25943029137293 + 20 +402.5 + 11 +-13.12500000000001 + 21 +402.5 + 0 +LINE + 5 +C9 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +46.25943029137293 + 20 +450 + 11 +-13.12500000000001 + 21 +450 + 0 +ENDBLK + 5 +63 +330 +61 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +65 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D25 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D25 + 1 + + 0 +LINE + 5 +CA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-29.99999999999997 + 20 +435 + 11 +-30 + 21 +15 + 0 +SOLID + 5 +CB +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-29.99999999999997 + 20 +435 + 30 +0 + 11 +-28.95928835556787 + 21 +428.75 + 31 +0 + 12 +-31.04071164443207 + 22 +428.75 + 32 +0 + 13 +-31.04071164443207 + 23 +428.75 + 33 +0 + 0 +SOLID + 5 +CC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-30 + 20 +15 + 30 +0 + 11 +-31.0407116444321 + 21 +21.25 + 31 +0 + 12 +-28.9592883555679 + 22 +21.25 + 32 +0 + 13 +-28.9592883555679 + 23 +21.25 + 33 +0 + 0 +MTEXT + 5 +CD +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +-34.68749999999999 + 20 +225 + 30 +0 + 40 +6.25 + 41 +13.19444444444444 + 71 + 5 + 72 + 1 + 1 +420 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +CE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-1.5625 + 20 +435 + 11 +-33.12499999999997 + 21 +435 + 0 +LINE + 5 +CF +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-1.5625 + 20 +15 + 11 +-33.125 + 21 +15 + 0 +ENDBLK + 5 +66 +330 +64 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +68 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D6 + 1 + + 0 +LINE + 5 +D0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +225 + 20 +-30 + 11 +0 + 21 +-30 + 0 +SOLID + 5 +D1 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +225 + 20 +-30 + 30 +0 + 11 +218.75 + 21 +-31.0407116444321 + 31 +0 + 12 +218.75 + 22 +-28.9592883555679 + 32 +0 + 13 +218.75 + 23 +-28.9592883555679 + 33 +0 + 0 +SOLID + 5 +D2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +0 + 20 +-30 + 30 +0 + 11 +6.25 + 21 +-28.9592883555679 + 31 +0 + 12 +6.25 + 22 +-31.0407116444321 + 32 +0 + 13 +6.25 + 23 +-31.0407116444321 + 33 +0 + 0 +MTEXT + 5 +D3 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +112.5 + 20 +-25.3125 + 30 +0 + 40 +6.25 + 41 +12.50000000000039 + 71 + 5 + 72 + 1 + 1 +225 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +360 + 73 + 2 + 44 +1 + 0 +LINE + 5 +D4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +225 + 20 +53.4375 + 11 +225 + 21 +-33.125 + 0 +LINE + 5 +D5 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-2.870171141771197e-016 + 20 +53.4375 + 11 +-5.740342283542393e-016 + 21 +-33.125 + 0 +ENDBLK + 5 +69 +330 +67 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6B +330 +6A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D20 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D20 + 1 + + 0 +LINE + 5 +D6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +40 + 20 +349 + 11 +40 + 21 +318 + 0 +SOLID + 5 +D7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +40 + 20 +349 + 30 +0 + 11 +41.0407116444321 + 21 +342.75 + 31 +0 + 12 +38.9592883555679 + 22 +342.75 + 32 +0 + 13 +38.9592883555679 + 23 +342.75 + 33 +0 + 0 +SOLID + 5 +D8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +40 + 20 +318 + 30 +0 + 11 +38.9592883555679 + 21 +324.25 + 31 +0 + 12 +41.0407116444321 + 22 +324.25 + 32 +0 + 13 +41.0407116444321 + 23 +324.25 + 33 +0 + 0 +MTEXT + 5 +D9 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +35.3125 + 20 +333.5 + 30 +0 + 40 +6.25 + 41 +6.250000000000387 + 71 + 5 + 72 + 1 + 1 +31 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +DA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +60.9375 + 20 +349 + 11 +36.875 + 21 +349 + 0 +LINE + 5 +DB +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +60.9375 + 20 +318 + 11 +36.875 + 21 +318 + 0 +ENDBLK + 5 +6C +330 +6A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6E +330 +6D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D7 + 1 + + 0 +LINE + 5 +DC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +460 + 11 +402.5 + 21 +460 + 0 +SOLID + 5 +DD +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +47.5 + 20 +460 + 30 +0 + 11 +53.75 + 21 +461.0407116444321 + 31 +0 + 12 +53.75 + 22 +458.9592883555679 + 32 +0 + 13 +53.75 + 23 +458.9592883555679 + 33 +0 + 0 +SOLID + 5 +DE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +402.5 + 20 +460 + 30 +0 + 11 +396.25 + 21 +458.9592883555679 + 31 +0 + 12 +396.25 + 22 +461.0407116444321 + 32 +0 + 13 +396.25 + 23 +461.0407116444321 + 33 +0 + 0 +MTEXT + 5 +DF +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +225 + 20 +464.6875 + 30 +0 + 40 +6.25 + 41 +12.50000000000116 + 71 + 5 + 72 + 1 + 1 +355 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +E0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +404.0625 + 11 +47.5 + 21 +463.125 + 0 +LINE + 5 +E1 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +402.5 + 20 +404.0625 + 11 +402.5 + 21 +463.125 + 0 +ENDBLK + 5 +6F +330 +6D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +71 +330 +70 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D1 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D1 + 1 + + 0 +LINE + 5 +E2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +425 + 20 +-20 + 11 +450 + 21 +-20 + 0 +SOLID + 5 +E3 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +425 + 20 +-20 + 30 +0 + 11 +431.25 + 21 +-18.9592883555679 + 31 +0 + 12 +431.25 + 22 +-21.0407116444321 + 32 +0 + 13 +431.25 + 23 +-21.0407116444321 + 33 +0 + 0 +SOLID + 5 +E4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +450 + 20 +-20 + 30 +0 + 11 +443.75 + 21 +-21.0407116444321 + 31 +0 + 12 +443.75 + 22 +-18.9592883555679 + 32 +0 + 13 +443.75 + 23 +-18.9592883555679 + 33 +0 + 0 +MTEXT + 5 +E5 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +437.5 + 20 +-15.3125 + 30 +0 + 40 +6.25 + 41 +7.638888888889277 + 71 + 5 + 72 + 1 + 1 +25 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +E6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +425 + 20 +23.4375 + 11 +425 + 21 +-23.125 + 0 +LINE + 5 +E7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +450 + 20 +23.4375 + 11 +450 + 21 +-23.125 + 0 +ENDBLK + 5 +72 +330 +70 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +74 +330 +73 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D8 + 1 + + 0 +LINE + 5 +E8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +0 + 20 +480 + 11 +450 + 21 +480 + 0 +SOLID + 5 +E9 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +0 + 20 +480 + 30 +0 + 11 +6.25 + 21 +481.0407116444321 + 31 +0 + 12 +6.25 + 22 +478.9592883555679 + 32 +0 + 13 +6.25 + 23 +478.9592883555679 + 33 +0 + 0 +SOLID + 5 +EA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +450 + 20 +480 + 30 +0 + 11 +443.75 + 21 +478.9592883555679 + 31 +0 + 12 +443.75 + 22 +481.0407116444321 + 32 +0 + 13 +443.75 + 23 +481.0407116444321 + 33 +0 + 0 +MTEXT + 5 +EB +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +225 + 20 +484.6875 + 30 +0 + 40 +6.25 + 41 +13.19444444444483 + 71 + 5 + 72 + 1 + 1 +450 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +EC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +9.567237139237322e-017 + 20 +451.5625 + 11 +1.913447427847464e-016 + 21 +483.125 + 0 +LINE + 5 +ED +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +450 + 20 +451.5625 + 11 +450 + 21 +483.125 + 0 +ENDBLK + 5 +75 +330 +73 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +77 +330 +76 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D10 + 1 + + 0 +LINE + 5 +EE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-10.00000000000002 + 20 +62.5 + 11 +-10 + 21 +387.5 + 0 +SOLID + 5 +EF +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-10.00000000000002 + 20 +62.5 + 30 +0 + 11 +-11.04071164443212 + 21 +68.75 + 31 +0 + 12 +-8.959288355567915 + 22 +68.75 + 32 +0 + 13 +-8.959288355567915 + 23 +68.75 + 33 +0 + 0 +SOLID + 5 +F0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-10 + 20 +387.5 + 30 +0 + 11 +-8.959288355567899 + 21 +381.25 + 31 +0 + 12 +-11.0407116444321 + 22 +381.25 + 32 +0 + 13 +-11.0407116444321 + 23 +381.25 + 33 +0 + 0 +MTEXT + 5 +F1 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +-14.68750000000001 + 20 +225 + 30 +0 + 40 +6.25 + 41 +12.50000000000077 + 71 + 5 + 72 + 1 + 1 +325 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +F2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +45.9375 + 20 +62.5 + 11 +-13.12500000000002 + 21 +62.5 + 0 +LINE + 5 +F3 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +45.9375 + 20 +387.5 + 11 +-13.125 + 21 +387.5 + 0 +ENDBLK + 5 +78 +330 +76 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7A +330 +79 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D15 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D15 + 1 + + 0 +LINE + 5 +F4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +-9.999999999999996 + 20 +55.00000000000001 + 11 +-10 + 21 +3.463895836830489e-015 + 0 +SOLID + 5 +F5 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-9.999999999999996 + 20 +55.00000000000001 + 30 +0 + 11 +-8.959288355567896 + 21 +48.75000000000001 + 31 +0 + 12 +-11.0407116444321 + 22 +48.75000000000001 + 32 +0 + 13 +-11.0407116444321 + 23 +48.75000000000001 + 33 +0 + 0 +SOLID + 5 +F6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-10 + 20 +3.463895836830489e-015 + 30 +0 + 11 +-11.0407116444321 + 21 +6.250000000000004 + 31 +0 + 12 +-8.959288355567898 + 22 +6.250000000000004 + 32 +0 + 13 +-8.959288355567898 + 23 +6.250000000000004 + 33 +0 + 0 +MTEXT + 5 +F7 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +-14.6875 + 20 +27.5 + 30 +0 + 40 +6.25 + 41 +7.638888888889664 + 71 + 5 + 72 + 1 + 1 +55 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +F8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +53.4375 + 20 +55 + 11 +-13.125 + 21 +55.00000000000001 + 0 +LINE + 5 +F9 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +53.4375 + 20 +1.913447427847464e-016 + 11 +-13.125 + 21 +3.846585322399982e-015 + 0 +ENDBLK + 5 +7B +330 +79 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7D +330 +7C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D14 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D14 + 1 + + 0 +LINE + 5 +FA +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +225 + 20 +30 + 11 +47.5 + 21 +30 + 0 +SOLID + 5 +FB +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +225 + 20 +30 + 30 +0 + 11 +218.75 + 21 +28.9592883555679 + 31 +0 + 12 +218.75 + 22 +31.0407116444321 + 32 +0 + 13 +218.75 + 23 +31.0407116444321 + 33 +0 + 0 +SOLID + 5 +FC +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +47.5 + 20 +30 + 30 +0 + 11 +53.75 + 21 +31.0407116444321 + 31 +0 + 12 +53.75 + 22 +28.9592883555679 + 32 +0 + 13 +53.75 + 23 +28.9592883555679 + 33 +0 + 0 +MTEXT + 5 +FD +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +136.25 + 20 +34.6875 + 30 +0 + 40 +6.25 + 41 +18.40277777777816 + 71 + 5 + 72 + 1 + 1 +177,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +360 + 73 + 2 + 44 +1 + 0 +LINE + 5 +FE +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +225 + 20 +53.4375 + 11 +225 + 21 +26.875 + 0 +LINE + 5 +FF +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +53.4375 + 11 +47.5 + 21 +26.875 + 0 +ENDBLK + 5 +7E +330 +7C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +80 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D23 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D23 + 1 + + 0 +LINE + 5 +100 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +420 + 20 +382.5 + 11 +420 + 21 +351.5 + 0 +SOLID + 5 +101 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +382.5 + 30 +0 + 11 +421.0407116444321 + 21 +376.25 + 31 +0 + 12 +418.9592883555679 + 22 +376.25 + 32 +0 + 13 +418.9592883555679 + 23 +376.25 + 33 +0 + 0 +SOLID + 5 +102 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +351.5 + 30 +0 + 11 +418.9592883555679 + 21 +357.75 + 31 +0 + 12 +421.0407116444321 + 22 +357.75 + 32 +0 + 13 +421.0407116444321 + 23 +357.75 + 33 +0 + 0 +MTEXT + 5 +103 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +415.3125 + 20 +367 + 30 +0 + 40 +6.25 + 41 +6.250000000000387 + 71 + 5 + 72 + 1 + 1 +31 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +104 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +384.0625 + 20 +382.5 + 11 +423.125 + 21 +382.5 + 0 +LINE + 5 +105 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +384.0625 + 20 +351.5 + 11 +423.125 + 21 +351.5 + 0 +ENDBLK + 5 +81 +330 +7F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +83 +330 +82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D2 + 1 + + 0 +LINE + 5 +106 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +365.9090909089 + 20 +-30 + 11 +450 + 21 +-30 + 0 +SOLID + 5 +107 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +365.9090909089 + 20 +-30 + 30 +0 + 11 +372.1590909089 + 21 +-28.9592883555679 + 31 +0 + 12 +372.1590909089 + 22 +-31.0407116444321 + 32 +0 + 13 +372.1590909089 + 23 +-31.0407116444321 + 33 +0 + 0 +SOLID + 5 +108 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +450 + 20 +-30 + 30 +0 + 11 +443.75 + 21 +-31.0407116444321 + 31 +0 + 12 +443.75 + 22 +-28.9592883555679 + 32 +0 + 13 +443.75 + 23 +-28.9592883555679 + 33 +0 + 0 +MTEXT + 5 +109 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +407.95454545445 + 20 +-25.3125 + 30 +0 + 40 +6.25 + 41 +20.48611111111111 + 71 + 5 + 72 + 1 + 1 +84,09 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +10A +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +365.9090909089 + 20 +83.9375 + 11 +365.9090909089 + 21 +-33.125 + 0 +LINE + 5 +10B +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +450 + 20 +83.9375 + 11 +450 + 21 +-33.125 + 0 +ENDBLK + 5 +84 +330 +82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +86 +330 +85 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D9 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D9 + 1 + + 0 +LINE + 5 +10C +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +410 + 20 +460 + 11 +435 + 21 +460 + 0 +SOLID + 5 +10D +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +410 + 20 +460 + 30 +0 + 11 +416.25 + 21 +461.0407116444321 + 31 +0 + 12 +416.25 + 22 +458.9592883555679 + 32 +0 + 13 +416.25 + 23 +458.9592883555679 + 33 +0 + 0 +SOLID + 5 +10E +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +435 + 20 +460 + 30 +0 + 11 +428.75 + 21 +458.9592883555679 + 31 +0 + 12 +428.75 + 22 +461.0407116444321 + 32 +0 + 13 +428.75 + 23 +461.0407116444321 + 33 +0 + 0 +MTEXT + 5 +10F +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +422.5 + 20 +464.6875 + 30 +0 + 40 +6.25 + 41 +7.638888888889277 + 71 + 5 + 72 + 1 + 1 +25 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +110 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +410 + 20 +416.5625 + 11 +410 + 21 +463.125 + 0 +LINE + 5 +111 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +435 + 20 +416.5625 + 11 +435 + 21 +463.125 + 0 +ENDBLK + 5 +87 +330 +85 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +89 +330 +88 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D3 + 1 + + 0 +LINE + 5 +112 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +470 + 20 +25 + 11 +470 + 21 +0 + 0 +SOLID + 5 +113 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +470 + 20 +25 + 30 +0 + 11 +471.0407116444321 + 21 +18.75 + 31 +0 + 12 +468.9592883555679 + 22 +18.75 + 32 +0 + 13 +468.9592883555679 + 23 +18.75 + 33 +0 + 0 +SOLID + 5 +114 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +470 + 20 +0 + 30 +0 + 11 +468.9592883555679 + 21 +6.25 + 31 +0 + 12 +471.0407116444321 + 22 +6.25 + 32 +0 + 13 +471.0407116444321 + 23 +6.25 + 33 +0 + 0 +MTEXT + 5 +115 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +465.3125 + 20 +12.5 + 30 +0 + 40 +6.25 + 41 +7.638888888889277 + 71 + 5 + 72 + 1 + 1 +25 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +116 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +426.5625 + 20 +25 + 11 +473.125 + 21 +25 + 0 +LINE + 5 +117 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +426.5625 + 20 +0 + 11 +473.125 + 21 +0 + 0 +ENDBLK + 5 +8A +330 +88 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8C +330 +8B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D24 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D24 + 1 + + 0 +LINE + 5 +118 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +420 + 20 +346.5 + 11 +420 + 21 +320.5 + 0 +SOLID + 5 +119 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +346.5 + 30 +0 + 11 +421.0407116444321 + 21 +340.25 + 31 +0 + 12 +418.9592883555679 + 22 +340.25 + 32 +0 + 13 +418.9592883555679 + 23 +340.25 + 33 +0 + 0 +SOLID + 5 +11A +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +420 + 20 +320.5 + 30 +0 + 11 +418.9592883555679 + 21 +326.75 + 31 +0 + 12 +421.0407116444321 + 22 +326.75 + 32 +0 + 13 +421.0407116444321 + 23 +326.75 + 33 +0 + 0 +MTEXT + 5 +11B +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +415.3125 + 20 +333.5 + 30 +0 + 40 +6.25 + 41 +7.638888888889277 + 71 + 5 + 72 + 1 + 1 +26 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +11C +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +384.0625 + 20 +346.5 + 11 +423.125 + 21 +346.5 + 0 +LINE + 5 +11D +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +384.0625 + 20 +320.5 + 11 +423.125 + 21 +320.5 + 0 +ENDBLK + 5 +8D +330 +8B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8F +330 +8E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D11 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D11 + 1 + + 0 +LINE + 5 +11E +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +460 + 11 +-3.944304526105059e-031 + 21 +460 + 0 +SOLID + 5 +11F +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +47.5 + 20 +460 + 30 +0 + 11 +41.25 + 21 +458.9592883555679 + 31 +0 + 12 +41.25 + 22 +461.0407116444321 + 32 +0 + 13 +41.25 + 23 +461.0407116444321 + 33 +0 + 0 +SOLID + 5 +120 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +-3.944304526105059e-031 + 20 +460 + 30 +0 + 11 +6.25 + 21 +461.0407116444321 + 31 +0 + 12 +6.25 + 22 +458.9592883555679 + 32 +0 + 13 +6.25 + 23 +458.9592883555679 + 33 +0 + 0 +MTEXT + 5 +121 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +23.75 + 20 +464.6875 + 30 +0 + 40 +6.25 + 41 +15.62500000000039 + 71 + 5 + 72 + 1 + 1 +47,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +360 + 73 + 2 + 44 +1 + 0 +LINE + 5 +122 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +47.5 + 20 +404.0625 + 11 +47.5 + 21 +463.125 + 0 +LINE + 5 +123 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +9.567237139237322e-017 + 20 +404.0625 + 11 +1.913447427847461e-016 + 21 +463.125 + 0 +ENDBLK + 5 +90 +330 +8E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +92 +330 +91 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D16 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D16 + 1 + + 0 +LINE + 5 +124 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +29.99999999999999 + 20 +62.5 + 11 +30 + 21 +225 + 0 +SOLID + 5 +125 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +29.99999999999999 + 20 +62.5 + 30 +0 + 11 +28.95928835556789 + 21 +68.75 + 31 +0 + 12 +31.04071164443209 + 22 +68.75 + 32 +0 + 13 +31.04071164443209 + 23 +68.75 + 33 +0 + 0 +SOLID + 5 +126 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +30 + 20 +225 + 30 +0 + 11 +31.0407116444321 + 21 +218.75 + 31 +0 + 12 +28.9592883555679 + 22 +218.75 + 32 +0 + 13 +28.9592883555679 + 23 +218.75 + 33 +0 + 0 +MTEXT + 5 +127 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +25.31249999999999 + 20 +143.75 + 30 +0 + 40 +6.25 + 41 +18.40277777777855 + 71 + 5 + 72 + 1 + 1 +162,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +90 + 73 + 2 + 44 +1 + 0 +LINE + 5 +128 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +53.4375 + 20 +62.5 + 11 +26.87499999999999 + 21 +62.5 + 0 +LINE + 5 +129 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +53.4375 + 20 +225 + 11 +26.875 + 21 +225 + 0 +ENDBLK + 5 +93 +330 +91 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +95 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D22 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D22 + 1 + + 0 +LINE + 5 +12A +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +98.18181818180001 + 20 +412.5 + 11 +126.3636363636 + 21 +412.5 + 0 +SOLID + 5 +12B +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +98.18181818180001 + 20 +412.5 + 30 +0 + 11 +104.4318181818 + 21 +413.5407116444321 + 31 +0 + 12 +104.4318181818 + 22 +411.4592883555679 + 32 +0 + 13 +104.4318181818 + 23 +411.4592883555679 + 33 +0 + 0 +SOLID + 5 +12C +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +126.3636363636 + 20 +412.5 + 30 +0 + 11 +120.1136363636 + 21 +411.4592883555679 + 31 +0 + 12 +120.1136363636 + 22 +413.5407116444321 + 32 +0 + 13 +120.1136363636 + 23 +413.5407116444321 + 33 +0 + 0 +MTEXT + 5 +12D +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +112.2727272727 + 20 +417.1875 + 30 +0 + 40 +6.25 + 41 +18.40277777777778 + 71 + 5 + 72 + 1 + 1 +28,18 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +12E +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +98.18181818180001 + 20 +389.0625 + 11 +98.18181818180001 + 21 +415.625 + 0 +LINE + 5 +12F +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +126.3636363636 + 20 +389.0625 + 11 +126.3636363636 + 21 +415.625 + 0 +ENDBLK + 5 +96 +330 +94 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +98 +330 +97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D18 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D18 + 1 + + 0 +LINE + 5 +130 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +337.7272727270999 + 20 +30 + 11 +365.9090909089 + 21 +30 + 0 +SOLID + 5 +131 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +337.7272727270999 + 20 +30 + 30 +0 + 11 +343.9772727270999 + 21 +31.0407116444321 + 31 +0 + 12 +343.9772727270999 + 22 +28.9592883555679 + 32 +0 + 13 +343.9772727270999 + 23 +28.9592883555679 + 33 +0 + 0 +SOLID + 5 +132 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +365.9090909089 + 20 +30 + 30 +0 + 11 +359.6590909089 + 21 +28.9592883555679 + 31 +0 + 12 +359.6590909089 + 22 +31.0407116444321 + 32 +0 + 13 +359.6590909089 + 23 +31.0407116444321 + 33 +0 + 0 +MTEXT + 5 +133 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +351.818181818 + 20 +34.6875 + 30 +0 + 40 +6.25 + 41 +18.40277777777778 + 71 + 5 + 72 + 1 + 1 +28,18 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +134 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +337.7272727270999 + 20 +83.9375 + 11 +337.7272727270999 + 21 +26.875 + 0 +LINE + 5 +135 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +365.9090909089 + 20 +83.9375 + 11 +365.9090909089 + 21 +26.875 + 0 +ENDBLK + 5 +99 +330 +97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9B +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D21 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D21 + 1 + + 0 +LINE + 5 +136 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +62.49999999999999 + 20 +412.5 + 11 +98.18181818180001 + 21 +412.5 + 0 +SOLID + 5 +137 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +62.49999999999999 + 20 +412.5 + 30 +0 + 11 +68.75 + 21 +413.5407116444321 + 31 +0 + 12 +68.75 + 22 +411.4592883555679 + 32 +0 + 13 +68.75 + 23 +411.4592883555679 + 33 +0 + 0 +SOLID + 5 +138 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +98.18181818180001 + 20 +412.5 + 30 +0 + 11 +91.93181818180001 + 21 +411.4592883555679 + 31 +0 + 12 +91.93181818180001 + 22 +413.5407116444321 + 32 +0 + 13 +91.93181818180001 + 23 +413.5407116444321 + 33 +0 + 0 +MTEXT + 5 +139 +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +80.3409090909 + 20 +417.1875 + 30 +0 + 40 +6.25 + 41 +19.79166666666783 + 71 + 5 + 72 + 1 + 1 +35,68 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +13A +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +62.5 + 20 +389.0625 + 11 +62.49999999999999 + 21 +415.625 + 0 +LINE + 5 +13B +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +98.18181818180001 + 20 +389.0625 + 11 +98.18181818180001 + 21 +415.625 + 0 +ENDBLK + 5 +9C +330 +9A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9E +330 +9D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D26 + 70 + 1 + 10 +0 + 20 +0 + 3 +*D26 + 1 + + 0 +LINE + 5 +13C +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +352 + 20 +410 + 11 +402.5 + 21 +410 + 0 +SOLID + 5 +13D +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +352 + 20 +410 + 30 +0 + 11 +358.25 + 21 +411.0407116444321 + 31 +0 + 12 +358.25 + 22 +408.9592883555679 + 32 +0 + 13 +358.25 + 23 +408.9592883555679 + 33 +0 + 0 +SOLID + 5 +13E +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbTrace + 10 +402.5 + 20 +410 + 30 +0 + 11 +396.25 + 21 +408.9592883555679 + 31 +0 + 12 +396.25 + 22 +411.0407116444321 + 32 +0 + 13 +396.25 + 23 +411.0407116444321 + 33 +0 + 0 +MTEXT + 5 +13F +100 +AcDbEntity + 8 +Dimensions + 6 +CONTINUOUS + 62 + 0 +370 + -2 +100 +AcDbMText + 10 +377.25 + 20 +414.6875 + 30 +0 + 40 +6.25 + 41 +14.93055555555633 + 71 + 5 + 72 + 1 + 1 +50,5 + 7 +STANDARD +210 +0 +220 +0 +230 +1 + 50 +0 + 73 + 2 + 44 +1 + 0 +LINE + 5 +140 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +352 + 20 +396.5625 + 11 +352 + 21 +413.125 + 0 +LINE + 5 +141 +100 +AcDbEntity + 8 +Dimensions + 6 +ByBlock + 62 + 0 +370 + -2 +100 +AcDbLine + 10 +402.5 + 20 +396.5625 + 11 +402.5 + 21 +413.125 + 0 +ENDBLK + 5 +9F +330 +9D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +142 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0 + 20 +0 + 11 +0 + 21 +450 + 0 +LINE + 5 +143 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0 + 20 +450 + 11 +450 + 21 +450 + 0 +LINE + 5 +144 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +450 + 20 +450 + 11 +450 + 21 +0 + 0 +LINE + 5 +145 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +450 + 20 +0 + 11 +0 + 21 +0 + 0 +LINE + 5 +146 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +435 + 11 +15 + 21 +15 + 0 +LINE + 5 +147 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +435 + 20 +435 + 11 +435 + 21 +15 + 0 +CIRCLE + 5 +148 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +55 + 20 +395 + 40 +5 + 0 +CIRCLE + 5 +149 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +395 + 40 +5 + 0 +CIRCLE + 5 +14A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +395 + 20 +395 + 40 +5 + 0 +CIRCLE + 5 +14B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +55 + 20 +225 + 40 +5 + 0 +CIRCLE + 5 +14C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +395 + 20 +225 + 40 +5 + 0 +CIRCLE + 5 +14D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +55 + 20 +55 + 40 +5 + 0 +CIRCLE + 5 +14E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +55 + 40 +5 + 0 +CIRCLE + 5 +14F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +395 + 20 +55 + 40 +5 + 0 +CIRCLE + 5 +150 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +25 + 20 +425 + 40 +2.5 + 0 +CIRCLE + 5 +151 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +425 + 20 +425 + 40 +2.5 + 0 +CIRCLE + 5 +152 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +25 + 20 +25 + 40 +2.5 + 0 +CIRCLE + 5 +153 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +425 + 20 +25 + 40 +2.5 + 0 +CIRCLE + 5 +154 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +155 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +156 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +157 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +158 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +159 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15A +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15B +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15C +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15D +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15E +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +85.5 + 40 +2.5 + 0 +CIRCLE + 5 +15F +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +160 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +161 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +162 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +163 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +164 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +165 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +166 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +167 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +168 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +169 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +116.5 + 40 +2.5 + 0 +CIRCLE + 5 +16A +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +16B +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +16C +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +16D +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +16E +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +16F +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +170 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +171 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +172 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +173 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +174 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +147.5 + 40 +2.5 + 0 +CIRCLE + 5 +175 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +176 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +177 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +178 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +179 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17A +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17B +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17C +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17D +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17E +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +17F +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +178.5 + 40 +2.5 + 0 +CIRCLE + 5 +180 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +181 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +182 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +183 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +184 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +185 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +186 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +187 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +188 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +189 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +18A +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +209.5 + 40 +2.5 + 0 +CIRCLE + 5 +18B +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +18C +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +18D +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +18E +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +18F +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +190 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +191 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +192 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +193 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +194 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +195 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +240.5 + 40 +2.5 + 0 +CIRCLE + 5 +196 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +197 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +198 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +199 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19A +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19B +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19C +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19D +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19E +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +19F +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A0 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +271.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A1 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A2 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A3 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A4 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A5 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A6 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A7 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A8 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1A9 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AA +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AB +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +302.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AC +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AD +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AE +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1AF +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B0 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B1 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B2 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B3 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B4 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B5 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B6 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +333.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B7 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +365.9090909089 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B8 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +337.7272727270999 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1B9 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +309.5454545453001 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BA +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +281.3636363635 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BB +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +253.1818181817 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BC +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +225 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BD +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +196.8181818181 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BE +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +168.6363636363 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1BF +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +140.4545454545 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1C0 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +112.2727272727 + 20 +364.5 + 40 +2.5 + 0 +CIRCLE + 5 +1C1 +100 +AcDbEntity + 8 +LEDs + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +84.0909090909 + 20 +364.5 + 40 +2.5 + 0 +LINE + 5 +1C2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +402.5 + 20 +62.5 + 11 +402.5 + 21 +47.5 + 0 +LINE + 5 +1C3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +402.5 + 20 +47.5 + 11 +47.5 + 21 +47.5 + 0 +LINE + 5 +1C4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +47.5 + 20 +47.5 + 11 +47.5 + 21 +62.5 + 0 +LINE + 5 +1C5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +47.5 + 20 +62.5 + 11 +402.5 + 21 +62.5 + 0 +LINE + 5 +1C6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +47.5 + 20 +402.5 + 11 +402.5 + 21 +402.5 + 0 +LINE + 5 +1C7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +402.5 + 20 +402.5 + 11 +402.5 + 21 +387.5 + 0 +LINE + 5 +1C8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +402.5 + 20 +387.5 + 11 +47.5 + 21 +387.5 + 0 +LINE + 5 +1C9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +47.5 + 20 +387.5 + 11 +47.5 + 21 +402.5 + 0 +DIMENSION + 5 +1CA +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D1 + 10 +450 + 20 +-20 + 30 +0 + 11 +437.5 + 21 +-15.3125 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +425 + 23 +25 + 33 +0 + 14 +450 + 24 +25 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1CB +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D2 + 10 +450 + 20 +-30 + 30 +0 + 11 +407.95454545445 + 21 +-25.3125 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +365.9090909089 + 23 +85.5 + 33 +0 + 14 +450 + 24 +85.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1CC +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D3 + 10 +470 + 20 +-5.510728592200698e-015 + 30 +0 + 11 +465.3125 + 21 +12.5 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +425 + 23 +25 + 33 +0 + 14 +425 + 24 +-0 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1CD +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D4 + 10 +480 + 20 +-1.397164521863323e-014 + 30 +0 + 11 +475.3125 + 21 +42.75000000000001 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +365.9090909089 + 23 +85.5 + 33 +0 + 14 +365.9090909089 + 24 +0 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +LINE + 5 +1CE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +410 + 20 +435 + 11 +410 + 21 +410 + 0 +LINE + 5 +1CF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +415 + 20 +435 + 11 +415 + 21 +415 + 0 +LINE + 5 +1D0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +410 + 20 +415 + 11 +435 + 21 +415 + 0 +LINE + 5 +1D1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +410 + 20 +410 + 11 +435 + 21 +410 + 0 +LINE + 5 +1D2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +47.5 + 20 +387.5 + 11 +47.5 + 21 +62.5 + 0 +LINE + 5 +1D3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +62.5 + 20 +387.5 + 11 +62.5 + 21 +62.49999999999999 + 0 +LINE + 5 +1D4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +402.5 + 20 +387.5 + 11 +402.5 + 21 +62.5 + 0 +LINE + 5 +1D5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +387.5 + 20 +387.5 + 11 +387.5 + 21 +62.50000000000001 + 0 +DIMENSION + 5 +1D6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D5 + 10 +-4.592273826833915e-015 + 20 +-20 + 30 +0 + 11 +27.5 + 21 +-15.3125 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +55 + 23 +55 + 33 +0 + 14 +0 + 24 +55 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1D7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D6 + 10 +-5.204577003745103e-015 + 20 +-30 + 30 +0 + 11 +112.5 + 21 +-25.3125 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +225 + 23 +55 + 33 +0 + 14 +0 + 24 +55 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1D8 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D7 + 10 +402.5 + 20 +460 + 30 +0 + 11 +225 + 21 +464.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +47.5 + 23 +402.5 + 33 +0 + 14 +402.5 + 24 +402.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1D9 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D8 + 10 +450 + 20 +480 + 30 +0 + 11 +225 + 21 +484.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +0 + 23 +450 + 33 +0 + 14 +450 + 24 +450 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DA +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D9 + 10 +435 + 20 +460 + 30 +0 + 11 +422.5 + 21 +464.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +410 + 23 +415 + 33 +0 + 14 +435 + 24 +415 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DB +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D10 + 10 +-10 + 20 +387.5 + 30 +0 + 11 +-14.68750000000001 + 21 +225 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +47.5 + 23 +62.5 + 33 +0 + 14 +47.5 + 24 +387.5 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DC +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D11 + 10 +3.520743267239335e-015 + 20 +460 + 30 +0 + 11 +23.75 + 21 +464.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +47.5 + 23 +402.5 + 33 +0 + 14 +0 + 24 +402.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DD +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D12 + 10 +-10.00000000000001 + 20 +450 + 30 +0 + 11 +-14.68750000000001 + 21 +426.25 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +47.82193029137293 + 23 +402.5 + 33 +0 + 14 +47.82193029137293 + 24 +450 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DE +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D13 + 10 +47.5 + 20 +30 + 30 +0 + 11 +51.25 + 21 +34.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +55 + 23 +55 + 33 +0 + 14 +47.5 + 24 +55 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1DF +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D14 + 10 +47.5 + 20 +30 + 30 +0 + 11 +136.25 + 21 +34.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +225 + 23 +55 + 33 +0 + 14 +47.5 + 24 +55 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E0 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D15 + 10 +-10 + 20 +7.959941299845452e-015 + 30 +0 + 11 +-14.6875 + 21 +27.5 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +55 + 23 +55 + 33 +0 + 14 +55 + 24 +0 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E1 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D16 + 10 +30 + 20 +225 + 30 +0 + 11 +25.31249999999999 + 21 +143.75 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +55 + 23 +62.5 + 33 +0 + 14 +55 + 24 +225 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E2 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D17 + 10 +420 + 20 +85.49999999999999 + 30 +0 + 11 +415.3125 + 21 +101 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +365.9090909089 + 23 +116.5 + 33 +0 + 14 +365.9090909089 + 24 +85.5 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E3 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D18 + 10 +365.9090909089 + 20 +30 + 30 +0 + 11 +351.818181818 + 21 +34.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +337.7272727270999 + 23 +85.5 + 33 +0 + 14 +365.9090909089 + 24 +85.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E4 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D19 + 10 +40 + 20 +349 + 30 +0 + 11 +35.3125 + 21 +368.25 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +62.5 + 23 +387.5 + 33 +0 + 14 +62.5 + 24 +349 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E5 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D20 + 10 +40 + 20 +318 + 30 +0 + 11 +35.3125 + 21 +333.5 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +62.5 + 23 +349 + 33 +0 + 14 +62.5 + 24 +318 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E6 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D21 + 10 +98.18181818180001 + 20 +412.5 + 30 +0 + 11 +80.3409090909 + 21 +417.1875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +62.5 + 23 +387.5 + 33 +0 + 14 +98.18181818180001 + 24 +387.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +1E7 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D22 + 10 +126.3636363636 + 20 +412.5 + 30 +0 + 11 +112.2727272727 + 21 +417.1875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +98.18181818180001 + 23 +387.5 + 33 +0 + 14 +126.3636363636 + 24 +387.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +1E8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +382.5 + 20 +387.5 + 11 +382.5 + 21 +62.50000000000001 + 0 +LINE + 5 +1E9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +387.5 + 11 +67.5 + 21 +62.49999999999999 + 0 +LINE + 5 +1EA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +382.5 + 20 +382.5 + 11 +67.5 + 21 +382.5 + 0 +LINE + 5 +1EB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +67.5 + 11 +382.5 + 21 +67.5 + 0 +LINE + 5 +1EC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +95.68181818180001 + 20 +67.5 + 11 +95.68181818180001 + 21 +382.5 + 0 +LINE + 5 +1ED +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +100.6818181818 + 20 +67.5 + 11 +100.6818181818 + 21 +382.5 + 0 +LINE + 5 +1EE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +123.8636363636 + 20 +67.5 + 11 +123.8636363636 + 21 +382.5 + 0 +LINE + 5 +1EF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +128.8636363636 + 20 +67.5 + 11 +128.8636363636 + 21 +382.5 + 0 +LINE + 5 +1F0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +152.0454545454 + 20 +67.5 + 11 +152.0454545454 + 21 +382.5 + 0 +LINE + 5 +1F1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +157.0454545454 + 20 +67.5 + 11 +157.0454545454 + 21 +382.5 + 0 +LINE + 5 +1F2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +180.2272727272 + 20 +67.5 + 11 +180.2272727272 + 21 +382.5 + 0 +LINE + 5 +1F3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +185.2272727272 + 20 +67.5 + 11 +185.2272727272 + 21 +382.5 + 0 +LINE + 5 +1F4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +208.409090909 + 20 +67.5 + 11 +208.409090909 + 21 +382.5 + 0 +LINE + 5 +1F5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +213.409090909 + 20 +67.5 + 11 +213.409090909 + 21 +382.5 + 0 +LINE + 5 +1F6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +236.5909090908 + 20 +67.5 + 11 +236.5909090908 + 21 +382.5 + 0 +LINE + 5 +1F7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +241.5909090908 + 20 +67.5 + 11 +241.5909090908 + 21 +382.5 + 0 +LINE + 5 +1F8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +264.7727272726 + 20 +67.5 + 11 +264.7727272726 + 21 +382.5 + 0 +LINE + 5 +1F9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +269.7727272726 + 20 +67.5 + 11 +269.7727272726 + 21 +382.5 + 0 +LINE + 5 +1FA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +292.9545454544 + 20 +67.5 + 11 +292.9545454544 + 21 +382.5 + 0 +LINE + 5 +1FB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +297.9545454544 + 20 +67.5 + 11 +297.9545454544 + 21 +382.5 + 0 +LINE + 5 +1FC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +321.1363636362 + 20 +67.5 + 11 +321.1363636362 + 21 +382.5 + 0 +LINE + 5 +1FD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +326.1363636362 + 20 +67.5 + 11 +326.1363636362 + 21 +382.5 + 0 +LINE + 5 +1FE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +349.3181818179999 + 20 +67.5 + 11 +349.3181818179999 + 21 +382.5 + 0 +LINE + 5 +1FF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +354.3181818179999 + 20 +67.5 + 11 +354.3181818179999 + 21 +382.5 + 0 +LINE + 5 +200 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +351.5 + 11 +382.5 + 21 +351.5 + 0 +LINE + 5 +201 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +346.5 + 11 +382.5 + 21 +346.5 + 0 +LINE + 5 +202 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +320.5 + 11 +382.5 + 21 +320.5 + 0 +LINE + 5 +203 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +315.5 + 11 +382.5 + 21 +315.5 + 0 +LINE + 5 +204 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +289.5 + 11 +382.5 + 21 +289.5 + 0 +LINE + 5 +205 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +284.5 + 11 +382.5 + 21 +284.5 + 0 +LINE + 5 +206 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +258.5 + 11 +382.5 + 21 +258.5 + 0 +LINE + 5 +207 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +253.5 + 11 +382.5 + 21 +253.5 + 0 +LINE + 5 +208 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +227.5 + 11 +382.5 + 21 +227.5 + 0 +LINE + 5 +209 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +222.5 + 11 +382.5 + 21 +222.5 + 0 +LINE + 5 +20A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +196.5 + 11 +382.5 + 21 +196.5 + 0 +LINE + 5 +20B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +191.5 + 11 +382.5 + 21 +191.5 + 0 +LINE + 5 +20C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +165.5 + 11 +382.5 + 21 +165.5 + 0 +LINE + 5 +20D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +160.5 + 11 +382.5 + 21 +160.5 + 0 +LINE + 5 +20E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +134.5 + 11 +382.5 + 21 +134.5 + 0 +LINE + 5 +20F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +129.5 + 11 +382.5 + 21 +129.5 + 0 +LINE + 5 +210 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +103.5 + 11 +382.5 + 21 +103.5 + 0 +LINE + 5 +211 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +67.5 + 20 +98.5 + 11 +382.5 + 21 +98.5 + 0 +DIMENSION + 5 +212 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D23 + 10 +420 + 20 +351.5 + 30 +0 + 11 +415.3125 + 21 +367 + 31 +0 + 70 + 32 + 71 + 5 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +382.5 + 23 +382.5 + 33 +0 + 14 +382.5 + 24 +351.5 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +213 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D24 + 10 +420 + 20 +320.5 + 30 +0 + 11 +415.3125 + 21 +333.5 + 31 +0 + 70 + 32 + 71 + 5 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +382.5 + 23 +346.5 + 33 +0 + 14 +382.5 + 24 +320.5 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +214 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D25 + 10 +-30 + 20 +15 + 30 +0 + 11 +-34.68749999999999 + 21 +225 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +0 + 23 +435 + 33 +0 + 14 +0 + 24 +15 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +CIRCLE + 5 +215 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +98 + 20 +396 + 40 +1 + 0 +CIRCLE + 5 +216 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +352 + 20 +395 + 40 +1 + 0 +DIMENSION + 5 +217 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D26 + 10 +402.5 + 20 +410 + 30 +0 + 11 +377.25 + 21 +414.6875 + 31 +0 + 70 + 32 + 71 + 5 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +352 + 23 +395 + 33 +0 + 14 +402.5 + 24 +395 + 34 +0 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +218 +100 +AcDbEntity + 8 +Dimensions + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 2 +*D27 + 10 +152.0454545454 + 20 +413 + 30 +0 + 11 +140.4545454545 + 21 +417.6875 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +128.8636363636 + 23 +382.5 + 33 +0 + 14 +152.0454545454 + 24 +382.5 + 34 +0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +219 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +435 + 11 +435 + 21 +435 + 0 +LINE + 5 +21A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +15 + 11 +435 + 21 +15 + 0 +LINE + 5 +21B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +15 + 11 +0 + 21 +0 + 0 +LINE + 5 +21C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +435 + 11 +0 + 21 +450 + 0 +LINE + 5 +21D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +435 + 20 +435 + 11 +450 + 21 +450 + 0 +LINE + 5 +21E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +435 + 20 +15 + 11 +450 + 21 +0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ENDSEC + 0 +EOF diff --git a/misc/Schematic.pdf b/src/misc/Schematic.pdf similarity index 100% rename from misc/Schematic.pdf rename to src/misc/Schematic.pdf diff --git a/test/README b/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html