├── .gitignore ├── .vscode └── settings.json ├── BuildLog.md ├── CAD ├── Clock_Servo_Support.step ├── Clock_Servo_Support.stl ├── Clock_Shaft_Support.step └── Clock_Shaft_Support.stl ├── LICENSE ├── README.md ├── fonts ├── Fonts.md └── acceptance_letter_by_decat_d55a2am.ttf ├── homeassistant ├── automations.yaml ├── configuration.yaml ├── gmailAutoarchive.js └── sensors.yaml ├── images ├── CAD_Clock_Assembly.PNG ├── CAD_Clock_Assembly_Front.PNG ├── CAD_servo_support.png ├── CAD_shaft_support.png ├── ClockHands.png ├── PrintableProps_Hands.jpg ├── WeasleyClockDiagram.png ├── WeasleyClockFace.jpeg ├── Weasley_clock_style1.gif ├── Weasley_clock_style2.jpg ├── Weasleyclock_motd.png ├── demo2.gif ├── demo3.gif └── homeassistant.png └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # emacs 107 | *~ 108 | .DS_Store -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.yaml": "home-assistant" 4 | }, 5 | "cSpell.words": [ 6 | "autoarchive", 7 | "Bryn", 8 | "geolocation", 9 | "Grabcad", 10 | "Hackaday", 11 | "HACS", 12 | "Hass", 13 | "intransit", 14 | "Konnected", 15 | "Minalima", 16 | "Quiddich", 17 | "Quidditch", 18 | "Quora", 19 | "Strava", 20 | "templating", 21 | "Traccar", 22 | "Unifi", 23 | "Weasley", 24 | "weasleyclock", 25 | "weasleyclockd", 26 | "Wheresly", 27 | "Woot", 28 | "Zwift" 29 | ] 30 | } -------------------------------------------------------------------------------- /BuildLog.md: -------------------------------------------------------------------------------- 1 | # Build Log 2 | 3 | I started this log after getting the Weasley Clock feature complete. I 4 | should have started from the beginning. Entries prior to April 2020 5 | are written retrospectively. 6 | 7 | ## TODO: Build/Code 8 | 9 | * create code/algorithm to reliably detect when people are bicycling for the Quidditch state 10 | * better document Zwift integration, post example home assistant configuration 11 | 12 | ## Why Home Assistant? 13 | 14 | I started using [Home Assistant](https://www.home-assistant.io/) when 15 | I was looking at home automation choices. What started this was my 16 | purchase from [Konnected](https://konnected.io/), a system that 17 | converts an old wired alarm system to a modern IoT integration. 18 | 19 | Home Assistant is open source and strives to keep all control local 20 | (and private) to your home network. 21 | 22 | After over a year of tinkering with Home Assistant, I feel like I've 23 | only scratched the surface of what it's capable of. 24 | 25 | I published [example configuration 26 | templates](https://github.com/randomstring/WeasleyClock/tree/master/homeassistant) 27 | for integrating into Home Assistant. 28 | 29 | ## Why Life360? 30 | 31 | I tried the Home Assistant Apple iCloud integration first. The iCloud 32 | API does not seem to be a fully supported and endorsed API. The Home 33 | Assistant integration broke for me at least twice. Once when Apple 34 | changed some details in their authentication. 35 | 36 | The Life360 integration has been quite stable and has features 37 | designed around tracking family members. I also managed to get buy-in 38 | from all my family members to use it. Which makes all of this possible. 39 | 40 | Another point is that it works on both iPhones and Android phones. 41 | 42 | Life360 allows for setting up several geo-fenced regions and giving 43 | them labels. For instance I have a geo-fence region for each school. 44 | Home Assistant also has this feature, so this can be done in Home 45 | Assistant just using the latitude and longitude provided by Life360. 46 | 47 | ## Why MQTT? 48 | 49 | MQTT is fairly easy to use, can generate arbitrary messages (I use 50 | JSON for the payload), and has extensive support in Home Assistant. 51 | 52 | Using python the [Paho MQTT](https://pypi.org/project/paho-mqtt/) 53 | module. 54 | 55 | I implemented the MQTT the Weasley Clock Server/Client in a stand 56 | alone repo called 57 | [weasleyclockd](https://github.com/randomstring/weasleyclockd). 58 | 59 | The other obvious choice would have been to use an HTTP and RESTful 60 | API. I haven't ruled out adding one. 61 | 62 | ## Monolithic Approach 63 | 64 | Alternatively, I could have just implemented a direct integration with 65 | Life360 on the Raspberry Pi. This would have taken the form of a 66 | single daemon running on the Weasley Clock that would poll Life360 and 67 | do all the state calculations. 68 | 69 | This would have been less complicated, removing the need for Home 70 | Assistant and the MQTT broker. There are a couple downsides to this 71 | approach. First, I would need to keep the Life360 API up to date in the 72 | event the API or the authentication scheme changed. If Life360 goes 73 | away for some reason, I can switch to some other location tracking 74 | system supported by Home Assistant. Secondly, I can leverage the Unifi 75 | Home Assistant integration to track which Wi-Fi AP people are connected 76 | to. AP level locations allow figuring out when someone is in the Shop 77 | or outside in the Garden. 78 | 79 | ## Clock Body Details 80 | 81 | I reused the original wood where possible to keep the aged look of the 82 | clock. When I needed to use new wood I stained it to match. 83 | 84 | I tried to use as much brass hardware as possible. 85 | 86 | ## Why Servos ? What other options? 87 | 88 | I used servos, because when I was looking at rotational control, this 89 | was what I found ready made solutions for first. I found multi 90 | rotation "sail" servos and the Pi Servo HAT solution first. 91 | 92 | Since then I've done some programming on robots. I think a motor with 93 | an encoder to track the location would be a better solution. The 94 | position control could be more precise and it would give the option of 95 | using PID and motion profiling to customize the hand movement. 96 | 97 | Maybe I'll make another version of the clockwork using motors and 98 | encoders. 99 | 100 | A third option would be to use stepper motors. I purchased a raspberry 101 | pi motor controller hat to test controlling stepper motors. 102 | 103 | Below are some seeds for future research. 104 | 105 | I found this possible motor and encoder combination: 106 | 107 | 108 | 109 | Another encoder option: 110 | 111 | 112 | 113 | Stepper motor with encoder: 114 | 115 | 116 | Possible motor from ServoCity.com: 117 | 118 | 119 | 120 | 121 | ## Notes on parts 122 | 123 | - 124 | NOTE: The 32 tooth gears don't fully clear the servo body. This 125 | means that to use more than one servo, we need to use a shaft so 126 | that central 64 tooth gears don't hit/interfere with the servos. 127 | - Using 64 tooth gears mounted to the brass tubes. This gives a clean 128 | 1:2 ration from the servos. 129 | - HS-785HB Servo 130 | - specs 131 | - Grabcad model 132 | - The HS-785HB Servos have a claimed 8 full rotations. I only need 133 | 2 full rotations to get the full range of motion of the clock 134 | hands. Having more than 360 degrees of motion allows for a little 135 | **flair** when positioning the hands. I'm going to use just 6 full 136 | rotations of the servo (so 3 full rotations of the hands) to 137 | avoid using the extremes of the PWM signals to the servos. 138 | - Stall current for HS-785HB is 1500mA. Max current 6A (at 5V?) 139 | - No load current for HS-785HB is 230mA 140 | - Idle current for HS-785HB is 9mA 141 | - possible screws for attaching to clamping hubs? 6-32 142 | - SKU 91771A145 length 0.3125" (5/16") < 0.333" = 0.25" (hub width) + 0.083" (screw head depth) 143 | - 144 | 145 | 146 | ## Why only 4 hands? 147 | 148 | When I first conceived of the idea, I expected to find a number of 149 | commercial multi-hand clockworks to choose from. There are plenty of 3 150 | hand clocks out there (hour, minute, seconds) and some are kits that 151 | would be hackable. I did not find any 4 or more clock hand solutions. 152 | 153 | Four was the minimum number I needed, as that was the size of my 154 | immediate family. I wanted to do more, ideally 7. That posed several 155 | problems. I was able to find a set of 7 consecutive nesting brass 156 | tubes 2, 3, 4, 5, 6, 7, and 8 mm. However I could not find clamping 157 | hubs in for 2mm, or 7mm sizes. Another challenge was fitting more than 158 | 4 servos around the central shaft. Finally, the depth of the clockwork 159 | would be almost double, making fitting it into a case more difficult. 160 | 161 | These are just problems to be overcome. 162 | 163 | # Diary 164 | 165 | ## 2019-02-07 Pi Servo HAT 166 | 167 | Ordered the [Adafruit 16-Channel PWM / Servo HAT for Raspberry 168 | Pi](https://www.adafruit.com/product/2327) to start experimenting with 169 | running servos. 170 | 171 | The servo HAT requires soldering on the headers. I watched a few 172 | YouTube videos like this one to learn how 173 | 174 | 175 | I got the larger capacity [5V 4A (4000mA) switching power 176 | supply](https://www.adafruit.com/product/1466) that can power more 177 | servos. This 4 Amps, might be overkill but at the time I didn't know 178 | which and how many servos I would need to drive. 179 | 180 | ## 2019-03-07 Brass Tubes 181 | 182 | Order a set of nesting brass tubes from Hobbylinc. I order them in 183 | metric whole millimeter sizes. The wall thickness on each is .45mm, 184 | leaving 0.1mm of clearance for the next smaller size of tube. 185 | 186 | Here is a link to the 4m size tube: 187 | 188 | 189 | I also get mounting hubs for attaching gears to the hubs 190 | . 191 | 192 | ## 2019-03-13 Order Servos and Gears 193 | 194 | Made my first order from [Servo City](https://www.servocity.com/) for 195 | a multi-turn "sail winch servo." Specifically the [HS 196 | 785hb](https://www.servocity.com/hs-785hb-servo) This is a servo that 197 | has a range of motion more than 360 degrees. Most servos have a range 198 | of less than 360 degree. 199 | 200 | I talk about other options for accurate rotation of for the clock 201 | hands, but at this point I had done enough research to know this 202 | should work. 203 | 204 | ## 2019-03-14 Thinking about Hands 205 | 206 | So I'd been thinking about how I was going to design, make, and 207 | ultimately attach clock hands. Of all the similar projects I found, by 208 | far the best was by [Printable 209 | Props](https://printableprops.jimdofree.com/en/harry-potter/weasley-clock/). I 210 | messaged the creator, Pascal, hoping he might share the CAD for his 211 | clock hands. He went full on authentic, artistically re-creating the 212 | hands from the movie. Sadly I didn't hear back. 213 | 214 | My friend Ben suggested outsourcing the hands to 215 | [Shapeways](https://www.shapeways.com/). I came pretty close to doing 216 | that. 217 | 218 | Thankfully, my son was enrolled in CAD and Advanced CAD at his high 219 | school. By the time I really needed the hands done, he was able to use 220 | his mad CAD skills to create custom hands in SolidWorks. 221 | 222 | 223 | ## 2019-06-19 Prototype Clockworks 224 | 225 | I build the first prototype of the clockworks and some [custom code to 226 | control the HS 785hb 227 | servos](https://github.com/randomstring/weasleyclockd/blob/master/hs785hb_servo.py). 228 | 229 | 230 | ## 2019-10-24 Thrift Store Gold! 231 | 232 | I had been thinking (and worrying) about how I was going to enclose 233 | the Weasley Clock. I was thinking of building a custom housing for it 234 | and mount it to the wall. This would have required improving my crude 235 | woodworking skills. 236 | 237 | Then I spotted this Grandfather clock in a thrift store in Langley, 238 | Washington. I had actually spotted this exact clock three months prior 239 | on a visit to Whidbey Island. At the time, I didn't have the 240 | measurements for the artwork and no way to tell if everything would 241 | fit. I was also traveling with my wife, for whom the clock was a 242 | surprise present, so I chose to be discrete and not start measuring the 243 | clock on the spot. 244 | 245 | Upon returning home, I measure the clockwork and artwork so I could 246 | identify old clocks that would fit. I did some searching on eBay.com 247 | for possible candidates, however working clocks were expensive and 248 | virtually all could not be shipped. Finding the perfect clock in 249 | Florida available for pick up only wasn't an option. 250 | 251 | Fate had me returning to Langley three months later and I went straight 252 | to the thrift shop. The clock was still there, and the price had come 253 | down $85. A few quick measurements later and I was positive I had a 254 | good fit. 255 | 256 | My wife was curious at my need to purchase the clock, but kept her 257 | curiosity in check as she knew it had something to with a surprise for 258 | her. 259 | 260 | Grandmother clock by Colonial MFG Co, Model 1866 $165 in a thrift store. 261 | 262 | 263 | ## 2020-02-20 Plug It In 264 | 265 | The pi and servos need power. The servos have their own power supply, 266 | so I needed at least two outlets inside the clock to provide power. I 267 | found this extension cord 268 | on Amazon. That fit 269 | with my sense of aesthetics for the clock. And because it was a dark 270 | gray, it's almost invisible inside the base of the clock. I also 271 | purchased a black pi USB power 272 | supply. 273 | 274 | I drilled a hole in the bottom of the clock big enough for the cable 275 | and then voided the warranty on the cord by cutting it, feeding the 276 | cable through and then splicing it back together. I didn't want to 277 | make a huge hole to squeeze the plug through. 278 | 279 | I ran the pair of black power cables for the pi and servos up the 280 | back, inside corner of the case. They are discreet enough that you 281 | don't see them, unless you're looking for them. 282 | 283 | ## 2020-04-01 Magic Wands 284 | 285 | Had the thought that I could create a replica Harry Potter magic wand 286 | with a strong magnet in the tip and install a few magnetic reed 287 | switches inside the clock. I could then pull out the want and tap the 288 | clock to trigger events. This would be a cool way to trigger a `Demo 289 | Mode`. 290 | 291 | ## 2020-04-04 MOTD 292 | 293 | Added a Harry Potter Themed message of the day. 294 | 295 | ![Message of the day](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/Weasleyclock_motd.png) 296 | 297 | ## 2020-04-05 Feature Complete! 298 | 299 | Thanks to my son's CAD design work for the clock hands, I now have a 300 | fully working Weasley clock. The clock is now installed in the kitchen. 301 | 302 | ## 2020-04-06 Make Garden Accurate 303 | 304 | Because the WiFi Access Point that I have reserved for outside is 305 | still inside near the front door, the clock will oscillate a person 306 | between `Garden` and `Home` if they walk through the front of the 307 | house. I needed to install the AP outside, near the garden. I've been 308 | putting this off as it wasn't on the critical path, until now. 309 | 310 | Today I got up on a ladder and installed the Unifi AP AC Pro outside 311 | near the garden. I thought that the AP AC Pro had pass-through POE, so 312 | I stole the POE connection for one of the Unifi G3 POE cameras to run 313 | the AP. Then I just daisy chained the G3 camera to the AP. Turns out, 314 | it's just a regular Ethernet port, no POE. I'll need to run another 315 | Cat6 cable to get the camera running again. 316 | 317 | Also started a new project on GitHub to [operate the grandfather clock 318 | chimes](https://github.com/randomstring/WeasleyChimes). 319 | 320 | ## 2020-04-07 More Cat6, MQTT Scripting 321 | 322 | Ran another Cat 6 cable to power the Unifi G3 camera. I managed to get 323 | the custom Cat 6 cable crimped correctly on the first try. One 324 | Ethernet jack was crimped while standing on a ladder. #winning 325 | 326 | Started writing `mqtt_script.py` a python program to send a scripted 327 | sequence of MQTT messages. I plan to use this to create demonstrations 328 | of what the Weasley Clock can do. The script should have other uses as 329 | well since it is not project specific and can send arbitrary MQTT 330 | messages. 331 | 332 | ## 2020-04-09 Zwift Integration & Documentation 333 | 334 | Added the [Zwift](https://zwift.com/) integration to Home Assistant 335 | . This required installing the 336 | [HACS](https://hacs.xyz/) community software store to Home 337 | Assistant. I need to look at HACS some more to see about adding and 338 | testing my own features. 339 | 340 | The clock now registers me in the state Quidditch whenever I'm 341 | actively riding on Zwift. 342 | 343 | Worked on cleaning up documentation. 344 | 345 | ## 2020-04-11 Diagram 346 | 347 | Spent the morning creating a pretty flow diagram for README.md. 348 | 349 | Researched quadrature encoders for the raspberry pi. 350 | 351 | ## 2020-04-12 CAD 352 | 353 | Add clock support CAD files. Remove ServoCity.com library CAD files, 354 | as they are hosted at . 355 | 356 | 357 | ## 2020-04-16 Painting and CAD 358 | 359 | I spent the last few days experimenting with painting the clock 360 | hands. The recipe I like is to clean up the 3D printed piece. Smooth 361 | it with a file and then emery paper. Next a layer of primer to help 362 | give it a smooth surface. Then paint with metallic nickle spray 363 | paint. Then mask off the letters of the name with blue painters 364 | tape. Then finish with a light, approximately 75% coverage of the hand 365 | with flat black paint. This lets a bit of the silver nickle shine 366 | through, but provides good contrast against the clock face. Final 367 | step is to remove the masking tape to reveal the names in bright 368 | silvery metallic nickle. 369 | 370 | Now I need to remove the hands from the clock, paint the hands, and 371 | then re-install them. 372 | 373 | I hired my son to create CAD files in SolidWorks of example clock 374 | hands with the Weasley family names from the Harry Potter movies. He 375 | also created a CAD rendering of the clockwork. 376 | 377 | I need to get those uploaded to GitHub and to Grabcad. 378 | 379 | ## 2020-04-17 Repaint 380 | 381 | Removed the 3D printed hands from the clock and started painting 382 | them. First primer coat applied. 383 | 384 | ## 2020-04-25 Finished painting 385 | 386 | Finished painting and reinstalled. Back up and running! With COVID-19, 387 | there isn't much movement other than people moving between "Home" and 388 | "Garden." 389 | 390 | ## 2020-04-26 391 | 392 | Worked on the MQTT script replay program to be able to demo various 393 | features. In the process the MQTT broker on my Home Assistant went a 394 | little wonky, I discovered that the broker I had installed was now 395 | deprecated, migrated to the supported MQTT HA broker, and in the 396 | process had no working MQTT for most of a day. It's all working now. 397 | 398 | Turns out port 4883 is a non-standard MQTT over SSL port. Switched to 399 | using port 8883. 400 | 401 | Fine tuning 402 | [demo2](https://github.com/randomstring/weasleyclockd/blob/master/demos/demo2.json) 403 | to demonstrate what happens when someone is far from home and then 404 | travels back home. 405 | 406 | ## 2020-05-01 407 | 408 | Figured out why the hand placement was off for some of the edges of 409 | some segments. I only just noticed that the the clock segments on the 410 | artwork are not all equally sized. I had assumed that all 8 segments 411 | were equal size and thus 45deg wide. Instead half of the segments are 412 | 40 degrees and half are 50 degrees. 413 | 414 | ## 2020-05-05 415 | 416 | Demo work. Improved demo scripts. Filmed stable video of demos. Made 417 | animated GIFs of demos. 418 | 419 | ``` 420 | ffmpeg -i IMG_7587.MOV -vf crop=1146:1080:387:0,scale=382:360,fps=6 demo2.gif 421 | ffmpeg -i IMG_7586.MOV -vf crop=1146:1080:387:0,scale=382:360,fps=6 demo3.gif 422 | ``` 423 | 424 | ## 2020-05-10 425 | 426 | I just found . This person made many of 427 | the same decisions I did, including using sail winch servos and 428 | reusing an antique clock body. No location tracking, or at least not 429 | when they last updated their webpage. 430 | 431 | ## 2020-05-17 3D Printed Gear Research 432 | 433 | Shopping around for alternate build options. 434 | 435 | Not sure why I overlooked McMaster-Carr in the past. 436 | https://www.mcmaster.com/shafts/copper-brass-and-bronze/system-of-measurement~metric/shape~round-tube/ 437 | 438 | Customizable Shaft Collar 439 | https://www.thingiverse.com/thing:3694236 440 | 441 | Examples of 3D printed shaft connectors. 442 | https://howtomechatronics.com/projects/arduino-3d-wire-bending-machine/ 443 | https://howtomechatronics.com/projects/arduino-mecanum-wheels-robot/ 444 | 445 | 3D printed motor mount and gears 446 | http://lukemetz.com/mechanical-v2-base/ 447 | 448 | Quora Ideas on how to attach 3D printed gears to metal shafts 449 | https://www.quora.com/What-is-the-best-way-to-secure-a-3D-printed-PLA-gear-to-a-metal-shaft 450 | 451 | ## 2020-05-19 452 | 453 | Wrote a blog post about the project, focused more on the non-technical side. https://randomstring2.blogspot.com/2020/05/weasley-location-clock-project.html It's been 5 years since my last blog post. Given how terrible blogger is, it might be another 5 before the next one. 454 | 455 | This project got onto the Hacker News front page. It got as high as #12 (that I saw). https://news.ycombinator.com/item?id=23235807 Woot! 456 | 457 | ## 2020-06-01 Detect when Bicycling 458 | 459 | This had been bothering me for a while. The Life360 moving state would 460 | be too easy to confusing with driving or even walking. I could use a 461 | range of speed that I assigned to be cycling. However, this would 462 | require implementing an average speed sensor. Even with the average 463 | speed, there are situations when I might be driving slowly (stuck in 464 | traffic) or biking quickly (down a long descent) that would be outside 465 | any fixed range. I could use geolocation to get street names and 466 | figure out when I'm on a bike train or an interstate and set the 467 | activity accordingly. I looked into ways to detect what device my 468 | phone was paired with via Bluetooth. If my phone was paired with my 469 | Garmin cycling computer, I would know I was cycling. I was starting to 470 | think I was going to have to write a complicated state machine as a 471 | custom plugin or script to make a reasonable guess at when I was 472 | biking or not. This is why I was procrastinating this task... 473 | 474 | In the end I took one last look at the Garmin LiveTrack feature. This 475 | will send an email with a URL for tracking your ride in real time. I 476 | use this email as a trigger when I start a ride and I use my return 477 | home as a trigger that the ride is over. In the future I'll work on 478 | actually pulling the URL from the email to detect when the ride is 479 | over. Or just time out after 2 hours of being stationary. 480 | 481 | Steps: 482 | - create a dummy gmail account to receive notifications 483 | - turn on LiveTracking on my Garmin 530 and send notifications to new gmail account 484 | - enable email sensor on HA https://www.home-assistant.io/integrations/imap_email_content/ 485 | - autoarchive new emails after 15 minutes 486 | see: https://medium.com/@fw3d/auto-archive-emails-in-gmail-after-2-days-1ebf0e076b1c 487 | - email sensor look for start of LiveTrack email, this signals start of ride 488 | - autoArchive script removes email after 15 min 489 | - end of ride when returning home 490 | 491 | 492 | Still to do is to flag the end of the ride even when not at home. This 493 | can be done by following the LiveTrack URL and monitor when the ride 494 | is actually over. Would be nice if there were an API. 495 | 496 | Strava used to have API access to the Strava Beacon feature, but it 497 | seems to be gone in the current API version. 498 | 499 | Alternatively, I can manually send an email to flag the end of a ride. 500 | 501 | # 2020-06-11 502 | 503 | Purchased a Wahoo ROAM bike computer. The Wahoo Fitness live track 504 | feature has a permanent URL so I can monitor a single URL to detect 505 | when I start and stop biking. Still need to write code to check the 506 | URL and parse out the biking state. 507 | 508 | Garmin sucks, so this was a welcome motivation to make the switch to 509 | Wahoo. Wahoo also has a cloud API in the works. 510 | 511 | 512 | # 2020-06-13 513 | 514 | Noticed that clock state sensor in HomeAssistant was not getting 515 | updated often enough. Only on major state transitions 'moving' to 516 | 'stationary' for instance. I added the home assistant proximity 517 | integration to add something with a value that would change as the 518 | person moved. I used meters as units so that even small movements 519 | would trigger a weasleyclock state update. 520 | 521 | # 2020-07-16 522 | 523 | This WeasleyClock project was included in the [GitHub Archive 524 | Program](https://archiveprogram.github.com/). Now when aliens unearth 525 | the wreckage of human civilization, they'll have instructions on how 526 | to build a WeasleyClock! 527 | 528 | # 2020-07-30 529 | 530 | This project got written up on Hackaday 531 | 532 | 533 | # 2020-07-31 534 | 535 | This project got written up on Tom's Hardware 536 | 537 | 538 | and made Tom's Hardware list of best Pi projects for August 2020: 539 | 540 | 541 | Made a first attempt at coding the Quiddich state detector using the 542 | iOS activity sensor. On iOS each activity has it's own state, true or 543 | false. However, the way that the Home Assistant app reports it is as a 544 | single state, and cycling is at the bottom of the reporting. So if 545 | Walking, Running, or driving is set to true, the Cycling state is 546 | never set. So I'm considering Walking and Running to be cycling if the 547 | speed is greater than 12 mph. 548 | 549 | I'm moving away from Garmin and today my email quidditch trigger took 550 | almost an hour to get delivered. This new detector should be more 551 | robust and it does not require any action on my part to trigger the 552 | Quidditch state. 553 | 554 | # 2020-09-06 Queue state changes 555 | 556 | So after living with the clock for a while some states can flip back 557 | and forth pretty quickly, especially between the Garden and Home 558 | states. These states are triggered by that person's phone connecting 559 | to different Wi-Fi access points and susceptible to the mysteries of 560 | wifi AP assignment. For instance, walking into the garage would 561 | sometimes trigger the Garden state. Worse, when near the house your 562 | phone might keep jumping between two APs (outside and inside) and the 563 | clock would just go nuts, swinging your clock hand back and forth 564 | between Garden and Home. 565 | 566 | My solution was to put a 30 second delay before moving the clock hands 567 | for certain states: Home, Garden, and Barn. This should cut down on 568 | some of the flailing. This is not perfect, and I should implement a 569 | proper queue. 570 | 571 | I made a second improvement to the staggered hand style. This style is 572 | now adaptive to how many hands were in that sector. If there's just 573 | one person in the Garden, that hand is right in the middle of the 574 | sector. If a second person goes into the garden that hand moves over 575 | to make room for the other hand. Likewise for 3 and 4 hands in the 576 | same sector. This gives the hand movement a more organic feel as the 577 | hands in the target sector move slightly as a new hand moves into the 578 | sector. 579 | 580 | After six months one of the hands occasionally squeaks. I didn't put 581 | any lubrication in the shafts or on the gears and I'm probably going 582 | to have to take it all apart and apply grease sometime soon. 583 | 584 | ## 2021-06-19 WhereslyClock 585 | 586 | This project inspired a new Weasley Clock project 587 | using Arduino, 588 | MQTT, and C. This is a lower budget build using more 3D printed parts 589 | and less expensive motors. Nicely done! 590 | 591 | 592 | ## 2021-07-02 Wahoo Live Updates 593 | 594 | I was hoping to use an API, but the Wahoo API that got published is 595 | focused on getting and updating activities and not on monitoring the 596 | live track. So I resorted to a very hackish way to extract the last 597 | update time for a user's live track. First you have to configure a 598 | permanent live track link. Then I use the Home Assistant command_line 599 | sensor to monitor how long it has been since the last live track 600 | update. When the update time goes below 5 minutes, I take that to mean 601 | I am cycling. This then triggers the Quidditch state. 602 | 603 | 604 | The command looks like this: 605 | 606 | ``` 607 | curl -s https://www.wahooligan.com/users/live/SECRET_URL | grep 'class=\"livetrack\"' | sed -E 's/.+data\\-seconds\\-since\\-update=\\\"([0-9]+)\\.[0-9]+\\\".+/\\1/'" 608 | ``` 609 | 610 | This is what goes into sensors.yaml. I keep the command in 611 | secrets.yaml, as the URL is a secret and there is no way to mix 612 | !secret directives into a command line action. 613 | 614 | ```yaml 615 | - platform: command_line 616 | command: !secret wahoo_command 617 | name: Bryn Last Actively Cycling 618 | unit_of_measurement: "seconds" 619 | command_timeout: 15 620 | scan_interval: 300 621 | ``` 622 | 623 | ## 2023-10-01 jinja macros 624 | 625 | Created Jinja templating macros to compute the home AP name and implement each sensor in HomeAssistant. This eliminates all the duplication of code and logic. 626 | 627 | Note to self: update the code in this github repo. 628 | 629 | ## 2024-01-01 No More Life360 630 | 631 | Life360 removed from HomeAssistant, because Life360 locked everyone out of their API access. 632 | I migrated to using the Apple iCloud integration. I added an automation that does a iCloud 633 | update whenever someone leaves home. The iCloud integration isn't as fast or frequent with 634 | location updates as life360 was, nor does it give speed information. I'm considering migrating 635 | to Traccar, but at the moment iCloud works just fine. 636 | 637 | 638 | # Specification 639 | 640 | Assorted measurements and specifications for parts. Pulling this out 641 | of the README to reduce clutter in the README. 642 | 643 | ## Clock Hand Dimensions 644 | 645 | Clock hands dimensions: 646 | 647 | - center-to-point: 88-92mm (so that the point does not obscure text) 648 | - width: 12-14mm (can vary, allow room for names) 649 | - thickness: 3mm (2mm was a little too thin) 650 | - max thickness around center hole: 4mm 651 | 652 | ## Clockwork Dimensions 653 | 654 | - clockwork depth: 4.125" (behind the face) 655 | - clockwork width: 6.625" 656 | - clockwork height: 3" 657 | - hands depth: 2" (with 0.125" clearance from glass) 658 | 659 | ## Clock Face Dimensions 660 | 661 | Clock face dimensions: 662 | - width 9.75" 663 | - height of square face 9.5" 664 | - total height 13.5" 665 | - top semi-circle indentation: 1" 666 | - top semi-circle height: 4" 667 | - clock face radius: 4" 668 | 669 | ## Clock Hand Ideas 670 | 671 | This section is a collection of ideas on other ways to create custom 672 | hands or make use of antique clock hands. 673 | 674 | Goals 675 | - mounting could be with 3D printing with a collet (clip) 676 | - Something like the metallic scissors w/ engraved names 677 | - clock hands could either be 3D printed or possibly laser cut from metal 678 | 679 | Resources: 680 | - https://www.bearwood.com/clock-hands-for-purchase.html 681 | - https://www.ebay.com/str/JRCLOCKER-Watches-and-Clocks 682 | - https://www.walnuthollow.com/store/clock-making/hands/ 683 | - https://www.cmi-hermle.com/category/40-handnuts-hand-bushes 684 | - https://www.cmi-hermle.com/category/38-hands-mechanical 685 | - https://www.clockworks.com/clock-parts/clock-parts.html 686 | - https://www.mcmaster.com/flanged-bushings Flanged for mounting flat clock hands 687 | - https://timesavers.com/c-325673-clock-repair-replacement-parts-hands-related-hand-bushings.html 688 | - https://perrinwatchparts.com/collections/clock-hand-nuts/products/clock-parts-740191?variant=39071940047 689 | - The clips to connect hands to the shaft are called collets 690 | - http://www.m-p.co.uk/muk/parts/hands-collets.htm 691 | 692 | 693 | ## Clock Hands Solution 694 | 695 | My son, Alex, generated the 3D CAD models for the hands with some 696 | artistic input from myself. In particular I spent a fair amount of 697 | time finding a good font to use. After a couple iterations they came 698 | out great! He put in a little extra time to make his clock hand have 699 | some extra flair. 700 | 701 | I kept the production in house. My father-in-law ran the 3D printer to 702 | print them. 703 | 704 | Attaching them to the brass rods turned out not to be an issue at 705 | all. The 3D hands were printed with slightly undersized holes. I filed 706 | out the holes so that they would fit, but very securely. 707 | 708 | ## Fonts 709 | 710 | Here are the [fonts](fonts/Fonts.md) I evaluated for use on the hands. 711 | -------------------------------------------------------------------------------- /CAD/Clock_Servo_Support.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/CAD/Clock_Servo_Support.stl -------------------------------------------------------------------------------- /CAD/Clock_Shaft_Support.step: -------------------------------------------------------------------------------- 1 | ISO-10303-21; 2 | HEADER; 3 | FILE_DESCRIPTION( ( '' ), ' ' ); 4 | FILE_NAME( '/vol/tmp/translate-1388519318224768741/5e9257b147ae4114db18601f.step', '2020-04-11T23:50:09', ( '' ), ( '' ), ' ', ' ', ' ' ); 5 | FILE_SCHEMA( ( 'AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }' ) ); 6 | ENDSEC; 7 | DATA; 8 | #1 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION( ' ', ( #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29, #30, #31 ), #6 ); 9 | #2 = PRODUCT_DEFINITION_CONTEXT( '', #32, 'design' ); 10 | #3 = APPLICATION_PROTOCOL_DEFINITION( 'international standard', 'automotive_design', 2001, #32 ); 11 | #4 = PRODUCT_CATEGORY_RELATIONSHIP( 'NONE', 'NONE', #33, #34 ); 12 | #5 = SHAPE_DEFINITION_REPRESENTATION( #35, #36 ); 13 | #6 = ( GEOMETRIC_REPRESENTATION_CONTEXT( 3 )GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT( ( #39 ) )GLOBAL_UNIT_ASSIGNED_CONTEXT( ( #41, #42, #43 ) )REPRESENTATION_CONTEXT( 'NONE', 'WORKSPACE' ) ); 14 | #10 = STYLED_ITEM( '', ( #45 ), #46 ); 15 | #11 = STYLED_ITEM( '', ( #47 ), #48 ); 16 | #12 = STYLED_ITEM( '', ( #49 ), #50 ); 17 | #13 = STYLED_ITEM( '', ( #51 ), #52 ); 18 | #14 = STYLED_ITEM( '', ( #53 ), #54 ); 19 | #15 = STYLED_ITEM( '', ( #55 ), #56 ); 20 | #16 = STYLED_ITEM( '', ( #57 ), #58 ); 21 | #17 = STYLED_ITEM( '', ( #59 ), #60 ); 22 | #18 = STYLED_ITEM( '', ( #61 ), #62 ); 23 | #19 = STYLED_ITEM( '', ( #63 ), #64 ); 24 | #20 = STYLED_ITEM( '', ( #65 ), #66 ); 25 | #21 = STYLED_ITEM( '', ( #67 ), #68 ); 26 | #22 = STYLED_ITEM( '', ( #69 ), #70 ); 27 | #23 = STYLED_ITEM( '', ( #71 ), #72 ); 28 | #24 = STYLED_ITEM( '', ( #73 ), #74 ); 29 | #25 = STYLED_ITEM( '', ( #75 ), #76 ); 30 | #26 = STYLED_ITEM( '', ( #77 ), #78 ); 31 | #27 = STYLED_ITEM( '', ( #79 ), #80 ); 32 | #28 = STYLED_ITEM( '', ( #81 ), #82 ); 33 | #29 = STYLED_ITEM( '', ( #83 ), #84 ); 34 | #30 = STYLED_ITEM( '', ( #85 ), #86 ); 35 | #31 = STYLED_ITEM( '', ( #87 ), #88 ); 36 | #32 = APPLICATION_CONTEXT( 'core data for automotive mechanical design processes' ); 37 | #33 = PRODUCT_CATEGORY( 'part', 'NONE' ); 38 | #34 = PRODUCT_RELATED_PRODUCT_CATEGORY( 'detail', ' ', ( #89 ) ); 39 | #35 = PRODUCT_DEFINITION_SHAPE( 'NONE', 'NONE', #90 ); 40 | #36 = ADVANCED_BREP_SHAPE_REPRESENTATION( 'Part 2', ( #91, #92 ), #6 ); 41 | #39 = UNCERTAINTY_MEASURE_WITH_UNIT( LENGTH_MEASURE( 1.00000000000000E-06 ), #41, '', '' ); 42 | #41 = ( CONVERSION_BASED_UNIT( 'METRE', #95 )LENGTH_UNIT( )NAMED_UNIT( #98 ) ); 43 | #42 = ( NAMED_UNIT( #100 )PLANE_ANGLE_UNIT( )SI_UNIT( $, .RADIAN. ) ); 44 | #43 = ( NAMED_UNIT( #100 )SI_UNIT( $, .STERADIAN. )SOLID_ANGLE_UNIT( ) ); 45 | #45 = PRESENTATION_STYLE_ASSIGNMENT( ( #106 ) ); 46 | #46 = ADVANCED_FACE( '', ( #107 ), #108, .F. ); 47 | #47 = PRESENTATION_STYLE_ASSIGNMENT( ( #109 ) ); 48 | #48 = ADVANCED_FACE( '', ( #110 ), #111, .F. ); 49 | #49 = PRESENTATION_STYLE_ASSIGNMENT( ( #112 ) ); 50 | #50 = ADVANCED_FACE( '', ( #113, #114 ), #115, .F. ); 51 | #51 = PRESENTATION_STYLE_ASSIGNMENT( ( #116 ) ); 52 | #52 = ADVANCED_FACE( '', ( #117, #118, #119 ), #120, .T. ); 53 | #53 = PRESENTATION_STYLE_ASSIGNMENT( ( #121 ) ); 54 | #54 = ADVANCED_FACE( '', ( #122 ), #123, .T. ); 55 | #55 = PRESENTATION_STYLE_ASSIGNMENT( ( #124 ) ); 56 | #56 = ADVANCED_FACE( '', ( #125 ), #126, .T. ); 57 | #57 = PRESENTATION_STYLE_ASSIGNMENT( ( #127 ) ); 58 | #58 = ADVANCED_FACE( '', ( #128 ), #129, .T. ); 59 | #59 = PRESENTATION_STYLE_ASSIGNMENT( ( #130 ) ); 60 | #60 = ADVANCED_FACE( '', ( #131, #132 ), #133, .F. ); 61 | #61 = PRESENTATION_STYLE_ASSIGNMENT( ( #134 ) ); 62 | #62 = ADVANCED_FACE( '', ( #135, #136 ), #137, .F. ); 63 | #63 = PRESENTATION_STYLE_ASSIGNMENT( ( #138 ) ); 64 | #64 = ADVANCED_FACE( '', ( #139, #140 ), #141, .F. ); 65 | #65 = PRESENTATION_STYLE_ASSIGNMENT( ( #142 ) ); 66 | #66 = ADVANCED_FACE( '', ( #143, #144 ), #145, .F. ); 67 | #67 = PRESENTATION_STYLE_ASSIGNMENT( ( #146 ) ); 68 | #68 = ADVANCED_FACE( '', ( #147, #148, #149, #150, #151, #152, #153, #154, #155, #156 ), #157, .F. ); 69 | #69 = PRESENTATION_STYLE_ASSIGNMENT( ( #158 ) ); 70 | #70 = ADVANCED_FACE( '', ( #159, #160, #161 ), #162, .T. ); 71 | #71 = PRESENTATION_STYLE_ASSIGNMENT( ( #163 ) ); 72 | #72 = ADVANCED_FACE( '', ( #164, #165 ), #166, .F. ); 73 | #73 = PRESENTATION_STYLE_ASSIGNMENT( ( #167 ) ); 74 | #74 = ADVANCED_FACE( '', ( #168, #169 ), #170, .F. ); 75 | #75 = PRESENTATION_STYLE_ASSIGNMENT( ( #171 ) ); 76 | #76 = ADVANCED_FACE( '', ( #172, #173 ), #174, .F. ); 77 | #77 = PRESENTATION_STYLE_ASSIGNMENT( ( #175 ) ); 78 | #78 = ADVANCED_FACE( '', ( #176, #177, #178, #179, #180, #181, #182, #183, #184, #185 ), #186, .T. ); 79 | #79 = PRESENTATION_STYLE_ASSIGNMENT( ( #187 ) ); 80 | #80 = ADVANCED_FACE( '', ( #188 ), #189, .F. ); 81 | #81 = PRESENTATION_STYLE_ASSIGNMENT( ( #190 ) ); 82 | #82 = ADVANCED_FACE( '', ( #191, #192 ), #193, .F. ); 83 | #83 = PRESENTATION_STYLE_ASSIGNMENT( ( #194 ) ); 84 | #84 = ADVANCED_FACE( '', ( #195 ), #196, .T. ); 85 | #85 = PRESENTATION_STYLE_ASSIGNMENT( ( #197 ) ); 86 | #86 = ADVANCED_FACE( '', ( #198, #199 ), #200, .F. ); 87 | #87 = PRESENTATION_STYLE_ASSIGNMENT( ( #201 ) ); 88 | #88 = ADVANCED_FACE( '', ( #202, #203 ), #204, .F. ); 89 | #89 = PRODUCT( 'Part 2', 'Part 2', 'PART-Part 2-DESC', ( #205 ) ); 90 | #90 = PRODUCT_DEFINITION( 'NONE', 'NONE', #206, #2 ); 91 | #91 = MANIFOLD_SOLID_BREP( 'Part 2', #207 ); 92 | #92 = AXIS2_PLACEMENT_3D( '', #208, #209, #210 ); 93 | #95 = LENGTH_MEASURE_WITH_UNIT( LENGTH_MEASURE( 1.00000000000000 ), #211 ); 94 | #98 = DIMENSIONAL_EXPONENTS( 1.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000 ); 95 | #100 = DIMENSIONAL_EXPONENTS( 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000, 0.00000000000000 ); 96 | #106 = SURFACE_STYLE_USAGE( .BOTH., #212 ); 97 | #107 = FACE_OUTER_BOUND( '', #213, .T. ); 98 | #108 = PLANE( '', #214 ); 99 | #109 = SURFACE_STYLE_USAGE( .BOTH., #215 ); 100 | #110 = FACE_OUTER_BOUND( '', #216, .T. ); 101 | #111 = CYLINDRICAL_SURFACE( '', #217, 0.00381000000000000 ); 102 | #112 = SURFACE_STYLE_USAGE( .BOTH., #218 ); 103 | #113 = FACE_OUTER_BOUND( '', #219, .T. ); 104 | #114 = FACE_OUTER_BOUND( '', #220, .T. ); 105 | #115 = CYLINDRICAL_SURFACE( '', #221, 0.00228600000000000 ); 106 | #116 = SURFACE_STYLE_USAGE( .BOTH., #222 ); 107 | #117 = FACE_BOUND( '', #223, .T. ); 108 | #118 = FACE_BOUND( '', #224, .T. ); 109 | #119 = FACE_OUTER_BOUND( '', #225, .T. ); 110 | #120 = PLANE( '', #226 ); 111 | #121 = SURFACE_STYLE_USAGE( .BOTH., #227 ); 112 | #122 = FACE_OUTER_BOUND( '', #228, .T. ); 113 | #123 = CYLINDRICAL_SURFACE( '', #229, 0.00317500000000000 ); 114 | #124 = SURFACE_STYLE_USAGE( .BOTH., #230 ); 115 | #125 = FACE_OUTER_BOUND( '', #231, .T. ); 116 | #126 = PLANE( '', #232 ); 117 | #127 = SURFACE_STYLE_USAGE( .BOTH., #233 ); 118 | #128 = FACE_OUTER_BOUND( '', #234, .T. ); 119 | #129 = PLANE( '', #235 ); 120 | #130 = SURFACE_STYLE_USAGE( .BOTH., #236 ); 121 | #131 = FACE_OUTER_BOUND( '', #237, .T. ); 122 | #132 = FACE_OUTER_BOUND( '', #238, .T. ); 123 | #133 = CYLINDRICAL_SURFACE( '', #239, 0.00228600000000000 ); 124 | #134 = SURFACE_STYLE_USAGE( .BOTH., #240 ); 125 | #135 = FACE_OUTER_BOUND( '', #241, .T. ); 126 | #136 = FACE_OUTER_BOUND( '', #242, .T. ); 127 | #137 = CYLINDRICAL_SURFACE( '', #243, 0.00368300000000000 ); 128 | #138 = SURFACE_STYLE_USAGE( .BOTH., #244 ); 129 | #139 = FACE_OUTER_BOUND( '', #245, .T. ); 130 | #140 = FACE_OUTER_BOUND( '', #246, .T. ); 131 | #141 = CYLINDRICAL_SURFACE( '', #247, 0.00228600000000000 ); 132 | #142 = SURFACE_STYLE_USAGE( .BOTH., #248 ); 133 | #143 = FACE_OUTER_BOUND( '', #249, .T. ); 134 | #144 = FACE_OUTER_BOUND( '', #250, .T. ); 135 | #145 = CYLINDRICAL_SURFACE( '', #251, 0.00325120000000000 ); 136 | #146 = SURFACE_STYLE_USAGE( .BOTH., #252 ); 137 | #147 = FACE_OUTER_BOUND( '', #253, .T. ); 138 | #148 = FACE_BOUND( '', #254, .T. ); 139 | #149 = FACE_BOUND( '', #255, .T. ); 140 | #150 = FACE_BOUND( '', #256, .T. ); 141 | #151 = FACE_BOUND( '', #257, .T. ); 142 | #152 = FACE_BOUND( '', #258, .T. ); 143 | #153 = FACE_BOUND( '', #259, .T. ); 144 | #154 = FACE_BOUND( '', #260, .T. ); 145 | #155 = FACE_BOUND( '', #261, .T. ); 146 | #156 = FACE_BOUND( '', #262, .T. ); 147 | #157 = PLANE( '', #263 ); 148 | #158 = SURFACE_STYLE_USAGE( .BOTH., #264 ); 149 | #159 = FACE_BOUND( '', #265, .T. ); 150 | #160 = FACE_BOUND( '', #266, .T. ); 151 | #161 = FACE_OUTER_BOUND( '', #267, .T. ); 152 | #162 = PLANE( '', #268 ); 153 | #163 = SURFACE_STYLE_USAGE( .BOTH., #269 ); 154 | #164 = FACE_OUTER_BOUND( '', #270, .T. ); 155 | #165 = FACE_OUTER_BOUND( '', #271, .T. ); 156 | #166 = CYLINDRICAL_SURFACE( '', #272, 0.00228600000000000 ); 157 | #167 = SURFACE_STYLE_USAGE( .BOTH., #273 ); 158 | #168 = FACE_OUTER_BOUND( '', #274, .T. ); 159 | #169 = FACE_OUTER_BOUND( '', #275, .T. ); 160 | #170 = CYLINDRICAL_SURFACE( '', #276, 0.00228600000000000 ); 161 | #171 = SURFACE_STYLE_USAGE( .BOTH., #277 ); 162 | #172 = FACE_OUTER_BOUND( '', #278, .T. ); 163 | #173 = FACE_OUTER_BOUND( '', #279, .T. ); 164 | #174 = CYLINDRICAL_SURFACE( '', #280, 0.00368300000000000 ); 165 | #175 = SURFACE_STYLE_USAGE( .BOTH., #281 ); 166 | #176 = FACE_BOUND( '', #282, .T. ); 167 | #177 = FACE_BOUND( '', #283, .T. ); 168 | #178 = FACE_BOUND( '', #284, .T. ); 169 | #179 = FACE_BOUND( '', #285, .T. ); 170 | #180 = FACE_BOUND( '', #286, .T. ); 171 | #181 = FACE_BOUND( '', #287, .T. ); 172 | #182 = FACE_BOUND( '', #288, .T. ); 173 | #183 = FACE_BOUND( '', #289, .T. ); 174 | #184 = FACE_BOUND( '', #290, .T. ); 175 | #185 = FACE_OUTER_BOUND( '', #291, .T. ); 176 | #186 = PLANE( '', #292 ); 177 | #187 = SURFACE_STYLE_USAGE( .BOTH., #293 ); 178 | #188 = FACE_OUTER_BOUND( '', #294, .T. ); 179 | #189 = PLANE( '', #295 ); 180 | #190 = SURFACE_STYLE_USAGE( .BOTH., #296 ); 181 | #191 = FACE_OUTER_BOUND( '', #297, .T. ); 182 | #192 = FACE_OUTER_BOUND( '', #298, .T. ); 183 | #193 = CYLINDRICAL_SURFACE( '', #299, 0.00368300000000000 ); 184 | #194 = SURFACE_STYLE_USAGE( .BOTH., #300 ); 185 | #195 = FACE_OUTER_BOUND( '', #301, .T. ); 186 | #196 = CYLINDRICAL_SURFACE( '', #302, 0.00317500000000000 ); 187 | #197 = SURFACE_STYLE_USAGE( .BOTH., #303 ); 188 | #198 = FACE_OUTER_BOUND( '', #304, .T. ); 189 | #199 = FACE_OUTER_BOUND( '', #305, .T. ); 190 | #200 = CYLINDRICAL_SURFACE( '', #306, 0.00368300000000000 ); 191 | #201 = SURFACE_STYLE_USAGE( .BOTH., #307 ); 192 | #202 = FACE_OUTER_BOUND( '', #308, .T. ); 193 | #203 = FACE_OUTER_BOUND( '', #309, .T. ); 194 | #204 = CYLINDRICAL_SURFACE( '', #310, 0.00228600000000000 ); 195 | #205 = PRODUCT_CONTEXT( '', #32, 'mechanical' ); 196 | #206 = PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE( ' ', 'NONE', #89, .NOT_KNOWN. ); 197 | #207 = CLOSED_SHELL( '', ( #48, #80, #56, #78, #60, #88, #70, #52, #46, #74, #84, #54, #82, #86, #62, #76, #66, #50, #72, #64, #68, #58 ) ); 198 | #208 = CARTESIAN_POINT( '', ( 0.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 199 | #209 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 200 | #210 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 201 | #211 = ( LENGTH_UNIT( )NAMED_UNIT( #98 )SI_UNIT( $, .METRE. ) ); 202 | #212 = SURFACE_SIDE_STYLE( '', ( #312 ) ); 203 | #213 = EDGE_LOOP( '', ( #313, #314, #315, #316 ) ); 204 | #214 = AXIS2_PLACEMENT_3D( '', #317, #318, #319 ); 205 | #215 = SURFACE_SIDE_STYLE( '', ( #320 ) ); 206 | #216 = EDGE_LOOP( '', ( #321, #322, #323, #324 ) ); 207 | #217 = AXIS2_PLACEMENT_3D( '', #325, #326, #327 ); 208 | #218 = SURFACE_SIDE_STYLE( '', ( #328 ) ); 209 | #219 = EDGE_LOOP( '', ( #329 ) ); 210 | #220 = EDGE_LOOP( '', ( #330 ) ); 211 | #221 = AXIS2_PLACEMENT_3D( '', #331, #332, #333 ); 212 | #222 = SURFACE_SIDE_STYLE( '', ( #334 ) ); 213 | #223 = EDGE_LOOP( '', ( #335 ) ); 214 | #224 = EDGE_LOOP( '', ( #336 ) ); 215 | #225 = EDGE_LOOP( '', ( #337, #338, #339, #340 ) ); 216 | #226 = AXIS2_PLACEMENT_3D( '', #341, #342, #343 ); 217 | #227 = SURFACE_SIDE_STYLE( '', ( #344 ) ); 218 | #228 = EDGE_LOOP( '', ( #345, #346, #347, #348 ) ); 219 | #229 = AXIS2_PLACEMENT_3D( '', #349, #350, #351 ); 220 | #230 = SURFACE_SIDE_STYLE( '', ( #352 ) ); 221 | #231 = EDGE_LOOP( '', ( #353, #354, #355, #356, #357, #358, #359 ) ); 222 | #232 = AXIS2_PLACEMENT_3D( '', #360, #361, #362 ); 223 | #233 = SURFACE_SIDE_STYLE( '', ( #363 ) ); 224 | #234 = EDGE_LOOP( '', ( #364, #365, #366, #367 ) ); 225 | #235 = AXIS2_PLACEMENT_3D( '', #368, #369, #370 ); 226 | #236 = SURFACE_SIDE_STYLE( '', ( #371 ) ); 227 | #237 = EDGE_LOOP( '', ( #372 ) ); 228 | #238 = EDGE_LOOP( '', ( #373 ) ); 229 | #239 = AXIS2_PLACEMENT_3D( '', #374, #375, #376 ); 230 | #240 = SURFACE_SIDE_STYLE( '', ( #377 ) ); 231 | #241 = EDGE_LOOP( '', ( #378 ) ); 232 | #242 = EDGE_LOOP( '', ( #379 ) ); 233 | #243 = AXIS2_PLACEMENT_3D( '', #380, #381, #382 ); 234 | #244 = SURFACE_SIDE_STYLE( '', ( #383 ) ); 235 | #245 = EDGE_LOOP( '', ( #384 ) ); 236 | #246 = EDGE_LOOP( '', ( #385 ) ); 237 | #247 = AXIS2_PLACEMENT_3D( '', #386, #387, #388 ); 238 | #248 = SURFACE_SIDE_STYLE( '', ( #389 ) ); 239 | #249 = EDGE_LOOP( '', ( #390 ) ); 240 | #250 = EDGE_LOOP( '', ( #391 ) ); 241 | #251 = AXIS2_PLACEMENT_3D( '', #392, #393, #394 ); 242 | #252 = SURFACE_SIDE_STYLE( '', ( #395 ) ); 243 | #253 = EDGE_LOOP( '', ( #396, #397, #398, #399, #400, #401 ) ); 244 | #254 = EDGE_LOOP( '', ( #402 ) ); 245 | #255 = EDGE_LOOP( '', ( #403 ) ); 246 | #256 = EDGE_LOOP( '', ( #404 ) ); 247 | #257 = EDGE_LOOP( '', ( #405 ) ); 248 | #258 = EDGE_LOOP( '', ( #406 ) ); 249 | #259 = EDGE_LOOP( '', ( #407 ) ); 250 | #260 = EDGE_LOOP( '', ( #408 ) ); 251 | #261 = EDGE_LOOP( '', ( #409 ) ); 252 | #262 = EDGE_LOOP( '', ( #410 ) ); 253 | #263 = AXIS2_PLACEMENT_3D( '', #411, #412, #413 ); 254 | #264 = SURFACE_SIDE_STYLE( '', ( #414 ) ); 255 | #265 = EDGE_LOOP( '', ( #415 ) ); 256 | #266 = EDGE_LOOP( '', ( #416 ) ); 257 | #267 = EDGE_LOOP( '', ( #417, #418, #419, #420 ) ); 258 | #268 = AXIS2_PLACEMENT_3D( '', #421, #422, #423 ); 259 | #269 = SURFACE_SIDE_STYLE( '', ( #424 ) ); 260 | #270 = EDGE_LOOP( '', ( #425 ) ); 261 | #271 = EDGE_LOOP( '', ( #426 ) ); 262 | #272 = AXIS2_PLACEMENT_3D( '', #427, #428, #429 ); 263 | #273 = SURFACE_SIDE_STYLE( '', ( #430 ) ); 264 | #274 = EDGE_LOOP( '', ( #431 ) ); 265 | #275 = EDGE_LOOP( '', ( #432 ) ); 266 | #276 = AXIS2_PLACEMENT_3D( '', #433, #434, #435 ); 267 | #277 = SURFACE_SIDE_STYLE( '', ( #436 ) ); 268 | #278 = EDGE_LOOP( '', ( #437 ) ); 269 | #279 = EDGE_LOOP( '', ( #438 ) ); 270 | #280 = AXIS2_PLACEMENT_3D( '', #439, #440, #441 ); 271 | #281 = SURFACE_SIDE_STYLE( '', ( #442 ) ); 272 | #282 = EDGE_LOOP( '', ( #443 ) ); 273 | #283 = EDGE_LOOP( '', ( #444 ) ); 274 | #284 = EDGE_LOOP( '', ( #445 ) ); 275 | #285 = EDGE_LOOP( '', ( #446 ) ); 276 | #286 = EDGE_LOOP( '', ( #447 ) ); 277 | #287 = EDGE_LOOP( '', ( #448 ) ); 278 | #288 = EDGE_LOOP( '', ( #449 ) ); 279 | #289 = EDGE_LOOP( '', ( #450 ) ); 280 | #290 = EDGE_LOOP( '', ( #451 ) ); 281 | #291 = EDGE_LOOP( '', ( #452, #453, #454, #455, #456, #457 ) ); 282 | #292 = AXIS2_PLACEMENT_3D( '', #458, #459, #460 ); 283 | #293 = SURFACE_SIDE_STYLE( '', ( #461 ) ); 284 | #294 = EDGE_LOOP( '', ( #462, #463, #464, #465, #466, #467, #468 ) ); 285 | #295 = AXIS2_PLACEMENT_3D( '', #469, #470, #471 ); 286 | #296 = SURFACE_SIDE_STYLE( '', ( #472 ) ); 287 | #297 = EDGE_LOOP( '', ( #473 ) ); 288 | #298 = EDGE_LOOP( '', ( #474 ) ); 289 | #299 = AXIS2_PLACEMENT_3D( '', #475, #476, #477 ); 290 | #300 = SURFACE_SIDE_STYLE( '', ( #478 ) ); 291 | #301 = EDGE_LOOP( '', ( #479, #480, #481, #482 ) ); 292 | #302 = AXIS2_PLACEMENT_3D( '', #483, #484, #485 ); 293 | #303 = SURFACE_SIDE_STYLE( '', ( #486 ) ); 294 | #304 = EDGE_LOOP( '', ( #487 ) ); 295 | #305 = EDGE_LOOP( '', ( #488 ) ); 296 | #306 = AXIS2_PLACEMENT_3D( '', #489, #490, #491 ); 297 | #307 = SURFACE_SIDE_STYLE( '', ( #492 ) ); 298 | #308 = EDGE_LOOP( '', ( #493 ) ); 299 | #309 = EDGE_LOOP( '', ( #494 ) ); 300 | #310 = AXIS2_PLACEMENT_3D( '', #495, #496, #497 ); 301 | #312 = SURFACE_STYLE_FILL_AREA( #498 ); 302 | #313 = ORIENTED_EDGE( '', *, *, #499, .T. ); 303 | #314 = ORIENTED_EDGE( '', *, *, #500, .F. ); 304 | #315 = ORIENTED_EDGE( '', *, *, #501, .F. ); 305 | #316 = ORIENTED_EDGE( '', *, *, #502, .T. ); 306 | #317 = CARTESIAN_POINT( '', ( 6.93889390390723E-18, -0.00508000000000000, 0.0635000000000000 ) ); 307 | #318 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 308 | #319 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 309 | #320 = SURFACE_STYLE_FILL_AREA( #503 ); 310 | #321 = ORIENTED_EDGE( '', *, *, #504, .F. ); 311 | #322 = ORIENTED_EDGE( '', *, *, #505, .F. ); 312 | #323 = ORIENTED_EDGE( '', *, *, #506, .F. ); 313 | #324 = ORIENTED_EDGE( '', *, *, #507, .F. ); 314 | #325 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00889000000000000, -0.0546100000000000 ) ); 315 | #326 = DIRECTION( '', ( 1.00000000000000, -0.00000000000000, -0.00000000000000 ) ); 316 | #327 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 317 | #328 = SURFACE_STYLE_FILL_AREA( #508 ); 318 | #329 = ORIENTED_EDGE( '', *, *, #509, .T. ); 319 | #330 = ORIENTED_EDGE( '', *, *, #510, .F. ); 320 | #331 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0458506532013416 ) ); 321 | #332 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 322 | #333 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 323 | #334 = SURFACE_STYLE_FILL_AREA( #511 ); 324 | #335 = ORIENTED_EDGE( '', *, *, #512, .F. ); 325 | #336 = ORIENTED_EDGE( '', *, *, #513, .F. ); 326 | #337 = ORIENTED_EDGE( '', *, *, #514, .T. ); 327 | #338 = ORIENTED_EDGE( '', *, *, #505, .T. ); 328 | #339 = ORIENTED_EDGE( '', *, *, #515, .F. ); 329 | #340 = ORIENTED_EDGE( '', *, *, #516, .T. ); 330 | #341 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.0241300000000000, -0.0584200000000000 ) ); 331 | #342 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 332 | #343 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 333 | #344 = SURFACE_STYLE_FILL_AREA( #517 ); 334 | #345 = ORIENTED_EDGE( '', *, *, #518, .T. ); 335 | #346 = ORIENTED_EDGE( '', *, *, #519, .F. ); 336 | #347 = ORIENTED_EDGE( '', *, *, #520, .F. ); 337 | #348 = ORIENTED_EDGE( '', *, *, #500, .T. ); 338 | #349 = CARTESIAN_POINT( '', ( -0.0412750000000000, -0.00508000000000000, 0.0603250000000000 ) ); 339 | #350 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 340 | #351 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 341 | #352 = SURFACE_STYLE_FILL_AREA( #521 ); 342 | #353 = ORIENTED_EDGE( '', *, *, #522, .F. ); 343 | #354 = ORIENTED_EDGE( '', *, *, #523, .F. ); 344 | #355 = ORIENTED_EDGE( '', *, *, #524, .T. ); 345 | #356 = ORIENTED_EDGE( '', *, *, #515, .T. ); 346 | #357 = ORIENTED_EDGE( '', *, *, #504, .T. ); 347 | #358 = ORIENTED_EDGE( '', *, *, #525, .T. ); 348 | #359 = ORIENTED_EDGE( '', *, *, #519, .T. ); 349 | #360 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, -0.00158750000000000 ) ); 350 | #361 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 5.60379075623439E-17 ) ); 351 | #362 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 352 | #363 = SURFACE_STYLE_FILL_AREA( #526 ); 353 | #364 = ORIENTED_EDGE( '', *, *, #516, .F. ); 354 | #365 = ORIENTED_EDGE( '', *, *, #524, .F. ); 355 | #366 = ORIENTED_EDGE( '', *, *, #527, .F. ); 356 | #367 = ORIENTED_EDGE( '', *, *, #528, .T. ); 357 | #368 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.0241300000000000, -1.38777878078145E-17 ) ); 358 | #369 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 359 | #370 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 360 | #371 = SURFACE_STYLE_FILL_AREA( #529 ); 361 | #372 = ORIENTED_EDGE( '', *, *, #530, .F. ); 362 | #373 = ORIENTED_EDGE( '', *, *, #512, .T. ); 363 | #374 = CARTESIAN_POINT( '', ( -0.0317500000000000, -0.0165100000000000, -0.215996767115427 ) ); 364 | #375 = DIRECTION( '', ( -0.00000000000000, -0.00000000000000, -1.00000000000000 ) ); 365 | #376 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 366 | #377 = SURFACE_STYLE_FILL_AREA( #531 ); 367 | #378 = ORIENTED_EDGE( '', *, *, #532, .T. ); 368 | #379 = ORIENTED_EDGE( '', *, *, #533, .F. ); 369 | #380 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0214385630115454 ) ); 370 | #381 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 371 | #382 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 372 | #383 = SURFACE_STYLE_FILL_AREA( #534 ); 373 | #384 = ORIENTED_EDGE( '', *, *, #535, .T. ); 374 | #385 = ORIENTED_EDGE( '', *, *, #536, .F. ); 375 | #386 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0458506532013416 ) ); 376 | #387 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 377 | #388 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 378 | #389 = SURFACE_STYLE_FILL_AREA( #537 ); 379 | #390 = ORIENTED_EDGE( '', *, *, #538, .T. ); 380 | #391 = ORIENTED_EDGE( '', *, *, #539, .F. ); 381 | #392 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00508000000000000, 1.99078583669394E-19 ) ); 382 | #393 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 383 | #394 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 384 | #395 = SURFACE_STYLE_FILL_AREA( #540 ); 385 | #396 = ORIENTED_EDGE( '', *, *, #522, .T. ); 386 | #397 = ORIENTED_EDGE( '', *, *, #518, .F. ); 387 | #398 = ORIENTED_EDGE( '', *, *, #499, .F. ); 388 | #399 = ORIENTED_EDGE( '', *, *, #541, .F. ); 389 | #400 = ORIENTED_EDGE( '', *, *, #542, .F. ); 390 | #401 = ORIENTED_EDGE( '', *, *, #543, .T. ); 391 | #402 = ORIENTED_EDGE( '', *, *, #544, .T. ); 392 | #403 = ORIENTED_EDGE( '', *, *, #545, .T. ); 393 | #404 = ORIENTED_EDGE( '', *, *, #533, .T. ); 394 | #405 = ORIENTED_EDGE( '', *, *, #546, .T. ); 395 | #406 = ORIENTED_EDGE( '', *, *, #539, .T. ); 396 | #407 = ORIENTED_EDGE( '', *, *, #510, .T. ); 397 | #408 = ORIENTED_EDGE( '', *, *, #547, .T. ); 398 | #409 = ORIENTED_EDGE( '', *, *, #548, .T. ); 399 | #410 = ORIENTED_EDGE( '', *, *, #536, .T. ); 400 | #411 = CARTESIAN_POINT( '', ( 0.00000000000000, 0.00000000000000, -1.38777878078145E-17 ) ); 401 | #412 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 402 | #413 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 403 | #414 = SURFACE_STYLE_FILL_AREA( #549 ); 404 | #415 = ORIENTED_EDGE( '', *, *, #530, .T. ); 405 | #416 = ORIENTED_EDGE( '', *, *, #550, .T. ); 406 | #417 = ORIENTED_EDGE( '', *, *, #543, .F. ); 407 | #418 = ORIENTED_EDGE( '', *, *, #551, .F. ); 408 | #419 = ORIENTED_EDGE( '', *, *, #527, .T. ); 409 | #420 = ORIENTED_EDGE( '', *, *, #523, .T. ); 410 | #421 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00508000000000000, -0.0635000000000000 ) ); 411 | #422 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 412 | #423 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 413 | #424 = SURFACE_STYLE_FILL_AREA( #552 ); 414 | #425 = ORIENTED_EDGE( '', *, *, #553, .T. ); 415 | #426 = ORIENTED_EDGE( '', *, *, #547, .F. ); 416 | #427 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0458506532013416 ) ); 417 | #428 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 418 | #429 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 419 | #430 = SURFACE_STYLE_FILL_AREA( #554 ); 420 | #431 = ORIENTED_EDGE( '', *, *, #555, .T. ); 421 | #432 = ORIENTED_EDGE( '', *, *, #548, .F. ); 422 | #433 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0458506532013416 ) ); 423 | #434 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 424 | #435 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 425 | #436 = SURFACE_STYLE_FILL_AREA( #556 ); 426 | #437 = ORIENTED_EDGE( '', *, *, #557, .T. ); 427 | #438 = ORIENTED_EDGE( '', *, *, #546, .F. ); 428 | #439 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0214385630115454 ) ); 429 | #440 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 430 | #441 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 431 | #442 = SURFACE_STYLE_FILL_AREA( #558 ); 432 | #443 = ORIENTED_EDGE( '', *, *, #559, .F. ); 433 | #444 = ORIENTED_EDGE( '', *, *, #560, .F. ); 434 | #445 = ORIENTED_EDGE( '', *, *, #532, .F. ); 435 | #446 = ORIENTED_EDGE( '', *, *, #557, .F. ); 436 | #447 = ORIENTED_EDGE( '', *, *, #538, .F. ); 437 | #448 = ORIENTED_EDGE( '', *, *, #509, .F. ); 438 | #449 = ORIENTED_EDGE( '', *, *, #553, .F. ); 439 | #450 = ORIENTED_EDGE( '', *, *, #555, .F. ); 440 | #451 = ORIENTED_EDGE( '', *, *, #535, .F. ); 441 | #452 = ORIENTED_EDGE( '', *, *, #525, .F. ); 442 | #453 = ORIENTED_EDGE( '', *, *, #507, .T. ); 443 | #454 = ORIENTED_EDGE( '', *, *, #561, .T. ); 444 | #455 = ORIENTED_EDGE( '', *, *, #562, .T. ); 445 | #456 = ORIENTED_EDGE( '', *, *, #501, .T. ); 446 | #457 = ORIENTED_EDGE( '', *, *, #520, .T. ); 447 | #458 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00508000000000000, -1.38777878078145E-17 ) ); 448 | #459 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 449 | #460 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 450 | #461 = SURFACE_STYLE_FILL_AREA( #563 ); 451 | #462 = ORIENTED_EDGE( '', *, *, #542, .T. ); 452 | #463 = ORIENTED_EDGE( '', *, *, #564, .F. ); 453 | #464 = ORIENTED_EDGE( '', *, *, #561, .F. ); 454 | #465 = ORIENTED_EDGE( '', *, *, #506, .T. ); 455 | #466 = ORIENTED_EDGE( '', *, *, #514, .F. ); 456 | #467 = ORIENTED_EDGE( '', *, *, #528, .F. ); 457 | #468 = ORIENTED_EDGE( '', *, *, #551, .T. ); 458 | #469 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, -0.00158750000000000 ) ); 459 | #470 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 5.60379075623439E-17 ) ); 460 | #471 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 461 | #472 = SURFACE_STYLE_FILL_AREA( #565 ); 462 | #473 = ORIENTED_EDGE( '', *, *, #559, .T. ); 463 | #474 = ORIENTED_EDGE( '', *, *, #544, .F. ); 464 | #475 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0214385630115454 ) ); 465 | #476 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 466 | #477 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 467 | #478 = SURFACE_STYLE_FILL_AREA( #566 ); 468 | #479 = ORIENTED_EDGE( '', *, *, #541, .T. ); 469 | #480 = ORIENTED_EDGE( '', *, *, #502, .F. ); 470 | #481 = ORIENTED_EDGE( '', *, *, #562, .F. ); 471 | #482 = ORIENTED_EDGE( '', *, *, #564, .T. ); 472 | #483 = CARTESIAN_POINT( '', ( 0.0412750000000000, -0.00508000000000000, 0.0603250000000000 ) ); 473 | #484 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 474 | #485 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 475 | #486 = SURFACE_STYLE_FILL_AREA( #567 ); 476 | #487 = ORIENTED_EDGE( '', *, *, #560, .T. ); 477 | #488 = ORIENTED_EDGE( '', *, *, #545, .F. ); 478 | #489 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0214385630115454 ) ); 479 | #490 = DIRECTION( '', ( -0.00000000000000, -1.00000000000000, -0.00000000000000 ) ); 480 | #491 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 481 | #492 = SURFACE_STYLE_FILL_AREA( #568 ); 482 | #493 = ORIENTED_EDGE( '', *, *, #550, .F. ); 483 | #494 = ORIENTED_EDGE( '', *, *, #513, .T. ); 484 | #495 = CARTESIAN_POINT( '', ( 0.0317500000000000, -0.0165100000000000, -0.215996767115427 ) ); 485 | #496 = DIRECTION( '', ( -0.00000000000000, -0.00000000000000, -1.00000000000000 ) ); 486 | #497 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 487 | #498 = FILL_AREA_STYLE( '', ( #569 ) ); 488 | #499 = EDGE_CURVE( '', #570, #571, #572, .T. ); 489 | #500 = EDGE_CURVE( '', #573, #571, #574, .T. ); 490 | #501 = EDGE_CURVE( '', #575, #573, #576, .T. ); 491 | #502 = EDGE_CURVE( '', #575, #570, #577, .T. ); 492 | #503 = FILL_AREA_STYLE( '', ( #578 ) ); 493 | #504 = EDGE_CURVE( '', #579, #580, #581, .F. ); 494 | #505 = EDGE_CURVE( '', #582, #579, #583, .F. ); 495 | #506 = EDGE_CURVE( '', #584, #582, #585, .T. ); 496 | #507 = EDGE_CURVE( '', #580, #584, #586, .T. ); 497 | #508 = FILL_AREA_STYLE( '', ( #587 ) ); 498 | #509 = EDGE_CURVE( '', #588, #588, #589, .T. ); 499 | #510 = EDGE_CURVE( '', #590, #590, #591, .T. ); 500 | #511 = FILL_AREA_STYLE( '', ( #592 ) ); 501 | #512 = EDGE_CURVE( '', #593, #593, #594, .T. ); 502 | #513 = EDGE_CURVE( '', #595, #595, #596, .T. ); 503 | #514 = EDGE_CURVE( '', #597, #582, #598, .T. ); 504 | #515 = EDGE_CURVE( '', #599, #579, #600, .T. ); 505 | #516 = EDGE_CURVE( '', #599, #597, #601, .T. ); 506 | #517 = FILL_AREA_STYLE( '', ( #602 ) ); 507 | #518 = EDGE_CURVE( '', #571, #603, #604, .T. ); 508 | #519 = EDGE_CURVE( '', #605, #603, #606, .T. ); 509 | #520 = EDGE_CURVE( '', #573, #605, #607, .T. ); 510 | #521 = FILL_AREA_STYLE( '', ( #608 ) ); 511 | #522 = EDGE_CURVE( '', #609, #603, #610, .T. ); 512 | #523 = EDGE_CURVE( '', #611, #609, #612, .T. ); 513 | #524 = EDGE_CURVE( '', #611, #599, #613, .T. ); 514 | #525 = EDGE_CURVE( '', #580, #605, #614, .T. ); 515 | #526 = FILL_AREA_STYLE( '', ( #615 ) ); 516 | #527 = EDGE_CURVE( '', #616, #611, #617, .T. ); 517 | #528 = EDGE_CURVE( '', #616, #597, #618, .T. ); 518 | #529 = FILL_AREA_STYLE( '', ( #619 ) ); 519 | #530 = EDGE_CURVE( '', #620, #620, #621, .F. ); 520 | #531 = FILL_AREA_STYLE( '', ( #622 ) ); 521 | #532 = EDGE_CURVE( '', #623, #623, #624, .T. ); 522 | #533 = EDGE_CURVE( '', #625, #625, #626, .T. ); 523 | #534 = FILL_AREA_STYLE( '', ( #627 ) ); 524 | #535 = EDGE_CURVE( '', #628, #628, #629, .T. ); 525 | #536 = EDGE_CURVE( '', #630, #630, #631, .T. ); 526 | #537 = FILL_AREA_STYLE( '', ( #632 ) ); 527 | #538 = EDGE_CURVE( '', #633, #633, #634, .T. ); 528 | #539 = EDGE_CURVE( '', #635, #635, #636, .T. ); 529 | #540 = FILL_AREA_STYLE( '', ( #637 ) ); 530 | #541 = EDGE_CURVE( '', #638, #570, #639, .T. ); 531 | #542 = EDGE_CURVE( '', #640, #638, #641, .T. ); 532 | #543 = EDGE_CURVE( '', #640, #609, #642, .T. ); 533 | #544 = EDGE_CURVE( '', #643, #643, #644, .T. ); 534 | #545 = EDGE_CURVE( '', #645, #645, #646, .T. ); 535 | #546 = EDGE_CURVE( '', #647, #647, #648, .T. ); 536 | #547 = EDGE_CURVE( '', #649, #649, #650, .T. ); 537 | #548 = EDGE_CURVE( '', #651, #651, #652, .T. ); 538 | #549 = FILL_AREA_STYLE( '', ( #653 ) ); 539 | #550 = EDGE_CURVE( '', #654, #654, #655, .F. ); 540 | #551 = EDGE_CURVE( '', #616, #640, #656, .T. ); 541 | #552 = FILL_AREA_STYLE( '', ( #657 ) ); 542 | #553 = EDGE_CURVE( '', #658, #658, #659, .T. ); 543 | #554 = FILL_AREA_STYLE( '', ( #660 ) ); 544 | #555 = EDGE_CURVE( '', #661, #661, #662, .T. ); 545 | #556 = FILL_AREA_STYLE( '', ( #663 ) ); 546 | #557 = EDGE_CURVE( '', #664, #664, #665, .T. ); 547 | #558 = FILL_AREA_STYLE( '', ( #666 ) ); 548 | #559 = EDGE_CURVE( '', #667, #667, #668, .T. ); 549 | #560 = EDGE_CURVE( '', #669, #669, #670, .T. ); 550 | #561 = EDGE_CURVE( '', #584, #671, #672, .T. ); 551 | #562 = EDGE_CURVE( '', #671, #575, #673, .T. ); 552 | #563 = FILL_AREA_STYLE( '', ( #674 ) ); 553 | #564 = EDGE_CURVE( '', #671, #638, #675, .T. ); 554 | #565 = FILL_AREA_STYLE( '', ( #676 ) ); 555 | #566 = FILL_AREA_STYLE( '', ( #677 ) ); 556 | #567 = FILL_AREA_STYLE( '', ( #678 ) ); 557 | #568 = FILL_AREA_STYLE( '', ( #679 ) ); 558 | #569 = FILL_AREA_STYLE_COLOUR( '', #680 ); 559 | #570 = VERTEX_POINT( '', #681 ); 560 | #571 = VERTEX_POINT( '', #682 ); 561 | #572 = LINE( '', #683, #684 ); 562 | #573 = VERTEX_POINT( '', #685 ); 563 | #574 = LINE( '', #686, #687 ); 564 | #575 = VERTEX_POINT( '', #688 ); 565 | #576 = LINE( '', #689, #690 ); 566 | #577 = LINE( '', #691, #692 ); 567 | #578 = FILL_AREA_STYLE_COLOUR( '', #693 ); 568 | #579 = VERTEX_POINT( '', #694 ); 569 | #580 = VERTEX_POINT( '', #695 ); 570 | #581 = CIRCLE( '', #696, 0.00381000000000000 ); 571 | #582 = VERTEX_POINT( '', #697 ); 572 | #583 = LINE( '', #698, #699 ); 573 | #584 = VERTEX_POINT( '', #700 ); 574 | #585 = CIRCLE( '', #701, 0.00381000000000000 ); 575 | #586 = LINE( '', #702, #703 ); 576 | #587 = FILL_AREA_STYLE_COLOUR( '', #704 ); 577 | #588 = VERTEX_POINT( '', #705 ); 578 | #589 = CIRCLE( '', #706, 0.00228600000000000 ); 579 | #590 = VERTEX_POINT( '', #707 ); 580 | #591 = CIRCLE( '', #708, 0.00228600000000000 ); 581 | #592 = FILL_AREA_STYLE_COLOUR( '', #709 ); 582 | #593 = VERTEX_POINT( '', #710 ); 583 | #594 = CIRCLE( '', #711, 0.00228600000000000 ); 584 | #595 = VERTEX_POINT( '', #712 ); 585 | #596 = CIRCLE( '', #713, 0.00228600000000000 ); 586 | #597 = VERTEX_POINT( '', #714 ); 587 | #598 = LINE( '', #715, #716 ); 588 | #599 = VERTEX_POINT( '', #717 ); 589 | #600 = LINE( '', #718, #719 ); 590 | #601 = LINE( '', #720, #721 ); 591 | #602 = FILL_AREA_STYLE_COLOUR( '', #722 ); 592 | #603 = VERTEX_POINT( '', #723 ); 593 | #604 = CIRCLE( '', #724, 0.00317500000000000 ); 594 | #605 = VERTEX_POINT( '', #725 ); 595 | #606 = LINE( '', #726, #727 ); 596 | #607 = CIRCLE( '', #728, 0.00317500000000000 ); 597 | #608 = FILL_AREA_STYLE_COLOUR( '', #729 ); 598 | #609 = VERTEX_POINT( '', #730 ); 599 | #610 = LINE( '', #731, #732 ); 600 | #611 = VERTEX_POINT( '', #733 ); 601 | #612 = LINE( '', #734, #735 ); 602 | #613 = LINE( '', #736, #737 ); 603 | #614 = LINE( '', #738, #739 ); 604 | #615 = FILL_AREA_STYLE_COLOUR( '', #740 ); 605 | #616 = VERTEX_POINT( '', #741 ); 606 | #617 = LINE( '', #742, #743 ); 607 | #618 = LINE( '', #744, #745 ); 608 | #619 = FILL_AREA_STYLE_COLOUR( '', #746 ); 609 | #620 = VERTEX_POINT( '', #747 ); 610 | #621 = CIRCLE( '', #748, 0.00228600000000000 ); 611 | #622 = FILL_AREA_STYLE_COLOUR( '', #749 ); 612 | #623 = VERTEX_POINT( '', #750 ); 613 | #624 = CIRCLE( '', #751, 0.00368300000000000 ); 614 | #625 = VERTEX_POINT( '', #752 ); 615 | #626 = CIRCLE( '', #753, 0.00368300000000000 ); 616 | #627 = FILL_AREA_STYLE_COLOUR( '', #754 ); 617 | #628 = VERTEX_POINT( '', #755 ); 618 | #629 = CIRCLE( '', #756, 0.00228600000000000 ); 619 | #630 = VERTEX_POINT( '', #757 ); 620 | #631 = CIRCLE( '', #758, 0.00228600000000000 ); 621 | #632 = FILL_AREA_STYLE_COLOUR( '', #759 ); 622 | #633 = VERTEX_POINT( '', #760 ); 623 | #634 = CIRCLE( '', #761, 0.00325120000000000 ); 624 | #635 = VERTEX_POINT( '', #762 ); 625 | #636 = CIRCLE( '', #763, 0.00325120000000000 ); 626 | #637 = FILL_AREA_STYLE_COLOUR( '', #764 ); 627 | #638 = VERTEX_POINT( '', #765 ); 628 | #639 = CIRCLE( '', #766, 0.00317500000000000 ); 629 | #640 = VERTEX_POINT( '', #767 ); 630 | #641 = LINE( '', #768, #769 ); 631 | #642 = LINE( '', #770, #771 ); 632 | #643 = VERTEX_POINT( '', #772 ); 633 | #644 = CIRCLE( '', #773, 0.00368300000000000 ); 634 | #645 = VERTEX_POINT( '', #774 ); 635 | #646 = CIRCLE( '', #775, 0.00368300000000000 ); 636 | #647 = VERTEX_POINT( '', #776 ); 637 | #648 = CIRCLE( '', #777, 0.00368300000000000 ); 638 | #649 = VERTEX_POINT( '', #778 ); 639 | #650 = CIRCLE( '', #779, 0.00228600000000000 ); 640 | #651 = VERTEX_POINT( '', #780 ); 641 | #652 = CIRCLE( '', #781, 0.00228600000000000 ); 642 | #653 = FILL_AREA_STYLE_COLOUR( '', #782 ); 643 | #654 = VERTEX_POINT( '', #783 ); 644 | #655 = CIRCLE( '', #784, 0.00228600000000000 ); 645 | #656 = LINE( '', #785, #786 ); 646 | #657 = FILL_AREA_STYLE_COLOUR( '', #787 ); 647 | #658 = VERTEX_POINT( '', #788 ); 648 | #659 = CIRCLE( '', #789, 0.00228600000000000 ); 649 | #660 = FILL_AREA_STYLE_COLOUR( '', #790 ); 650 | #661 = VERTEX_POINT( '', #791 ); 651 | #662 = CIRCLE( '', #792, 0.00228600000000000 ); 652 | #663 = FILL_AREA_STYLE_COLOUR( '', #793 ); 653 | #664 = VERTEX_POINT( '', #794 ); 654 | #665 = CIRCLE( '', #795, 0.00368300000000000 ); 655 | #666 = FILL_AREA_STYLE_COLOUR( '', #796 ); 656 | #667 = VERTEX_POINT( '', #797 ); 657 | #668 = CIRCLE( '', #798, 0.00368300000000000 ); 658 | #669 = VERTEX_POINT( '', #799 ); 659 | #670 = CIRCLE( '', #800, 0.00368300000000000 ); 660 | #671 = VERTEX_POINT( '', #801 ); 661 | #672 = LINE( '', #802, #803 ); 662 | #673 = CIRCLE( '', #804, 0.00317500000000000 ); 663 | #674 = FILL_AREA_STYLE_COLOUR( '', #805 ); 664 | #675 = LINE( '', #806, #807 ); 665 | #676 = FILL_AREA_STYLE_COLOUR( '', #808 ); 666 | #677 = FILL_AREA_STYLE_COLOUR( '', #809 ); 667 | #678 = FILL_AREA_STYLE_COLOUR( '', #810 ); 668 | #679 = FILL_AREA_STYLE_COLOUR( '', #811 ); 669 | #680 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 670 | #681 = CARTESIAN_POINT( '', ( 0.0412750000000000, 0.00000000000000, 0.0635000000000000 ) ); 671 | #682 = CARTESIAN_POINT( '', ( -0.0412750000000000, 0.00000000000000, 0.0635000000000000 ) ); 672 | #683 = CARTESIAN_POINT( '', ( 6.93889390390723E-18, 0.00000000000000, 0.0635000000000000 ) ); 673 | #684 = VECTOR( '', #812, 1.00000000000000 ); 674 | #685 = CARTESIAN_POINT( '', ( -0.0412750000000000, -0.00508000000000000, 0.0635000000000000 ) ); 675 | #686 = CARTESIAN_POINT( '', ( -0.0412750000000000, -0.00508000000000000, 0.0635000000000000 ) ); 676 | #687 = VECTOR( '', #813, 1.00000000000000 ); 677 | #688 = CARTESIAN_POINT( '', ( 0.0412750000000000, -0.00508000000000000, 0.0635000000000000 ) ); 678 | #689 = CARTESIAN_POINT( '', ( 6.93889390390723E-18, -0.00508000000000000, 0.0635000000000000 ) ); 679 | #690 = VECTOR( '', #814, 1.00000000000000 ); 680 | #691 = CARTESIAN_POINT( '', ( 0.0412750000000000, -0.00508000000000000, 0.0635000000000000 ) ); 681 | #692 = VECTOR( '', #815, 1.00000000000000 ); 682 | #693 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 683 | #694 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00889000000000000, -0.0584200000000000 ) ); 684 | #695 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, -0.0546100000000000 ) ); 685 | #696 = AXIS2_PLACEMENT_3D( '', #816, #817, #818 ); 686 | #697 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00889000000000000, -0.0584200000000000 ) ); 687 | #698 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00889000000000000, -0.0584200000000000 ) ); 688 | #699 = VECTOR( '', #819, 1.00000000000000 ); 689 | #700 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, -0.0546100000000000 ) ); 690 | #701 = AXIS2_PLACEMENT_3D( '', #820, #821, #822 ); 691 | #702 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, -0.0546100000000000 ) ); 692 | #703 = VECTOR( '', #823, 1.00000000000000 ); 693 | #704 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 694 | #705 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0435646532013416 ) ); 695 | #706 = AXIS2_PLACEMENT_3D( '', #824, #825, #826 ); 696 | #707 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, 0.0435646532013416 ) ); 697 | #708 = AXIS2_PLACEMENT_3D( '', #827, #828, #829 ); 698 | #709 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 699 | #710 = CARTESIAN_POINT( '', ( -0.0294640000000000, -0.0165100000000000, -0.0584200000000000 ) ); 700 | #711 = AXIS2_PLACEMENT_3D( '', #830, #831, #832 ); 701 | #712 = CARTESIAN_POINT( '', ( 0.0340360000000000, -0.0165100000000000, -0.0584200000000000 ) ); 702 | #713 = AXIS2_PLACEMENT_3D( '', #833, #834, #835 ); 703 | #714 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.0241300000000000, -0.0584200000000000 ) ); 704 | #715 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.0241300000000000, -0.0584200000000000 ) ); 705 | #716 = VECTOR( '', #836, 1.00000000000000 ); 706 | #717 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.0241300000000000, -0.0584200000000000 ) ); 707 | #718 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.0241300000000000, -0.0584200000000000 ) ); 708 | #719 = VECTOR( '', #837, 1.00000000000000 ); 709 | #720 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.0241300000000000, -0.0584200000000000 ) ); 710 | #721 = VECTOR( '', #838, 1.00000000000000 ); 711 | #722 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 712 | #723 = CARTESIAN_POINT( '', ( -0.0444500000000000, 0.00000000000000, 0.0603250000000000 ) ); 713 | #724 = AXIS2_PLACEMENT_3D( '', #839, #840, #841 ); 714 | #725 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, 0.0603250000000000 ) ); 715 | #726 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, 0.0603250000000000 ) ); 716 | #727 = VECTOR( '', #842, 1.00000000000000 ); 717 | #728 = AXIS2_PLACEMENT_3D( '', #843, #844, #845 ); 718 | #729 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 719 | #730 = CARTESIAN_POINT( '', ( -0.0444500000000000, 0.00000000000000, -0.0635000000000000 ) ); 720 | #731 = CARTESIAN_POINT( '', ( -0.0444500000000000, 0.00000000000000, -0.00158750000000000 ) ); 721 | #732 = VECTOR( '', #846, 1.00000000000000 ); 722 | #733 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.0241300000000000, -0.0635000000000000 ) ); 723 | #734 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, -0.0635000000000000 ) ); 724 | #735 = VECTOR( '', #847, 1.00000000000000 ); 725 | #736 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.0241300000000000, -0.00158750000000000 ) ); 726 | #737 = VECTOR( '', #848, 1.00000000000000 ); 727 | #738 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00508000000000000, -0.00158750000000000 ) ); 728 | #739 = VECTOR( '', #849, 1.00000000000000 ); 729 | #740 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 730 | #741 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.0241300000000000, -0.0635000000000000 ) ); 731 | #742 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.0241300000000000, -0.0635000000000000 ) ); 732 | #743 = VECTOR( '', #850, 1.00000000000000 ); 733 | #744 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.0241300000000000, -0.00158750000000000 ) ); 734 | #745 = VECTOR( '', #851, 1.00000000000000 ); 735 | #746 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 736 | #747 = CARTESIAN_POINT( '', ( -0.0340360000000000, -0.0165100000000000, -0.0635000000000000 ) ); 737 | #748 = AXIS2_PLACEMENT_3D( '', #852, #853, #854 ); 738 | #749 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 739 | #750 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0251215630115454 ) ); 740 | #751 = AXIS2_PLACEMENT_3D( '', #855, #856, #857 ); 741 | #752 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, -0.0251215630115454 ) ); 742 | #753 = AXIS2_PLACEMENT_3D( '', #858, #859, #860 ); 743 | #754 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 744 | #755 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0481366532013416 ) ); 745 | #756 = AXIS2_PLACEMENT_3D( '', #861, #862, #863 ); 746 | #757 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, -0.0481366532013416 ) ); 747 | #758 = AXIS2_PLACEMENT_3D( '', #864, #865, #866 ); 748 | #759 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 749 | #760 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00508000000000000, -0.00325120000000000 ) ); 750 | #761 = AXIS2_PLACEMENT_3D( '', #867, #868, #869 ); 751 | #762 = CARTESIAN_POINT( '', ( 0.00000000000000, 0.00000000000000, -0.00325120000000000 ) ); 752 | #763 = AXIS2_PLACEMENT_3D( '', #870, #871, #872 ); 753 | #764 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 754 | #765 = CARTESIAN_POINT( '', ( 0.0444500000000000, 0.00000000000000, 0.0603250000000000 ) ); 755 | #766 = AXIS2_PLACEMENT_3D( '', #873, #874, #875 ); 756 | #767 = CARTESIAN_POINT( '', ( 0.0444500000000000, 0.00000000000000, -0.0635000000000000 ) ); 757 | #768 = CARTESIAN_POINT( '', ( 0.0444500000000000, 0.00000000000000, -0.00158750000000000 ) ); 758 | #769 = VECTOR( '', #876, 1.00000000000000 ); 759 | #770 = CARTESIAN_POINT( '', ( 0.00000000000000, 0.00000000000000, -0.0635000000000000 ) ); 760 | #771 = VECTOR( '', #877, 1.00000000000000 ); 761 | #772 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, 0.0177555630115454 ) ); 762 | #773 = AXIS2_PLACEMENT_3D( '', #878, #879, #880 ); 763 | #774 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, 0.0177555630115454 ) ); 764 | #775 = AXIS2_PLACEMENT_3D( '', #881, #882, #883 ); 765 | #776 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, -0.0251215630115454 ) ); 766 | #777 = AXIS2_PLACEMENT_3D( '', #884, #885, #886 ); 767 | #778 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, 0.0435646532013416 ) ); 768 | #779 = AXIS2_PLACEMENT_3D( '', #887, #888, #889 ); 769 | #780 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, -0.0481366532013416 ) ); 770 | #781 = AXIS2_PLACEMENT_3D( '', #890, #891, #892 ); 771 | #782 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 772 | #783 = CARTESIAN_POINT( '', ( 0.0294640000000000, -0.0165100000000000, -0.0635000000000000 ) ); 773 | #784 = AXIS2_PLACEMENT_3D( '', #893, #894, #895 ); 774 | #785 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, -0.0635000000000000 ) ); 775 | #786 = VECTOR( '', #896, 1.00000000000000 ); 776 | #787 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 777 | #788 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0435646532013416 ) ); 778 | #789 = AXIS2_PLACEMENT_3D( '', #897, #898, #899 ); 779 | #790 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 780 | #791 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0481366532013416 ) ); 781 | #792 = AXIS2_PLACEMENT_3D( '', #900, #901, #902 ); 782 | #793 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 783 | #794 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0251215630115454 ) ); 784 | #795 = AXIS2_PLACEMENT_3D( '', #903, #904, #905 ); 785 | #796 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 786 | #797 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0177555630115454 ) ); 787 | #798 = AXIS2_PLACEMENT_3D( '', #906, #907, #908 ); 788 | #799 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0177555630115454 ) ); 789 | #800 = AXIS2_PLACEMENT_3D( '', #909, #910, #911 ); 790 | #801 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, 0.0603250000000000 ) ); 791 | #802 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, -0.00158750000000000 ) ); 792 | #803 = VECTOR( '', #912, 1.00000000000000 ); 793 | #804 = AXIS2_PLACEMENT_3D( '', #913, #914, #915 ); 794 | #805 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 795 | #806 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00508000000000000, 0.0603250000000000 ) ); 796 | #807 = VECTOR( '', #916, 1.00000000000000 ); 797 | #808 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 798 | #809 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 799 | #810 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 800 | #811 = COLOUR_RGB( '', 0.615686297400000, 0.811764717100000, 0.929411768900000 ); 801 | #812 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 802 | #813 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 803 | #814 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 804 | #815 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 805 | #816 = CARTESIAN_POINT( '', ( -0.0444500000000000, -0.00889000000000000, -0.0546100000000000 ) ); 806 | #817 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 5.60379075623439E-17 ) ); 807 | #818 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 808 | #819 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 809 | #820 = CARTESIAN_POINT( '', ( 0.0444500000000000, -0.00889000000000000, -0.0546100000000000 ) ); 810 | #821 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 5.60379075623439E-17 ) ); 811 | #822 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 812 | #823 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 813 | #824 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0458506532013416 ) ); 814 | #825 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 815 | #826 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 816 | #827 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, 0.0458506532013416 ) ); 817 | #828 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 818 | #829 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 819 | #830 = CARTESIAN_POINT( '', ( -0.0317500000000000, -0.0165100000000000, -0.0584200000000000 ) ); 820 | #831 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 821 | #832 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 822 | #833 = CARTESIAN_POINT( '', ( 0.0317500000000000, -0.0165100000000000, -0.0584200000000000 ) ); 823 | #834 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, 1.00000000000000 ) ); 824 | #835 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 825 | #836 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 826 | #837 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 827 | #838 = DIRECTION( '', ( 1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 828 | #839 = CARTESIAN_POINT( '', ( -0.0412750000000000, 0.00000000000000, 0.0603250000000000 ) ); 829 | #840 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 830 | #841 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 831 | #842 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 832 | #843 = CARTESIAN_POINT( '', ( -0.0412750000000000, -0.00508000000000000, 0.0603250000000000 ) ); 833 | #844 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 834 | #845 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 835 | #846 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 836 | #847 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 837 | #848 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 838 | #849 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 839 | #850 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 840 | #851 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 841 | #852 = CARTESIAN_POINT( '', ( -0.0317500000000000, -0.0165100000000000, -0.0635000000000000 ) ); 842 | #853 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 843 | #854 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 844 | #855 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0214385630115454 ) ); 845 | #856 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 846 | #857 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 847 | #858 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, -0.0214385630115454 ) ); 848 | #859 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 849 | #860 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 850 | #861 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0458506532013416 ) ); 851 | #862 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 852 | #863 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 853 | #864 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, -0.0458506532013416 ) ); 854 | #865 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 855 | #866 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 856 | #867 = CARTESIAN_POINT( '', ( 0.00000000000000, -0.00508000000000000, 1.99078583669394E-19 ) ); 857 | #868 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 858 | #869 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 859 | #870 = CARTESIAN_POINT( '', ( 0.00000000000000, 0.00000000000000, 1.99078583669394E-19 ) ); 860 | #871 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 861 | #872 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 862 | #873 = CARTESIAN_POINT( '', ( 0.0412750000000000, 0.00000000000000, 0.0603250000000000 ) ); 863 | #874 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 864 | #875 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 865 | #876 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 866 | #877 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 867 | #878 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, 0.0214385630115454 ) ); 868 | #879 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 869 | #880 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 870 | #881 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, 0.0214385630115454 ) ); 871 | #882 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 872 | #883 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 873 | #884 = CARTESIAN_POINT( '', ( -0.0314960000000000, 0.00000000000000, -0.0214385630115454 ) ); 874 | #885 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 875 | #886 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 876 | #887 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, 0.0458506532013416 ) ); 877 | #888 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 878 | #889 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 879 | #890 = CARTESIAN_POINT( '', ( 0.0314960000000000, 0.00000000000000, -0.0458506532013416 ) ); 880 | #891 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 881 | #892 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 882 | #893 = CARTESIAN_POINT( '', ( 0.0317500000000000, -0.0165100000000000, -0.0635000000000000 ) ); 883 | #894 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 884 | #895 = DIRECTION( '', ( -1.00000000000000, 0.00000000000000, 0.00000000000000 ) ); 885 | #896 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 886 | #897 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0458506532013416 ) ); 887 | #898 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 888 | #899 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 889 | #900 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, -0.0458506532013416 ) ); 890 | #901 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 891 | #902 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 892 | #903 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, -0.0214385630115454 ) ); 893 | #904 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 894 | #905 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 895 | #906 = CARTESIAN_POINT( '', ( -0.0314960000000000, -0.00508000000000000, 0.0214385630115454 ) ); 896 | #907 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 897 | #908 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 898 | #909 = CARTESIAN_POINT( '', ( 0.0314960000000000, -0.00508000000000000, 0.0214385630115454 ) ); 899 | #910 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 900 | #911 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 901 | #912 = DIRECTION( '', ( 5.60379075623439E-17, 0.00000000000000, 1.00000000000000 ) ); 902 | #913 = CARTESIAN_POINT( '', ( 0.0412750000000000, -0.00508000000000000, 0.0603250000000000 ) ); 903 | #914 = DIRECTION( '', ( 0.00000000000000, -1.00000000000000, 0.00000000000000 ) ); 904 | #915 = DIRECTION( '', ( 0.00000000000000, 0.00000000000000, -1.00000000000000 ) ); 905 | #916 = DIRECTION( '', ( 0.00000000000000, 1.00000000000000, 0.00000000000000 ) ); 906 | ENDSEC; 907 | END-ISO-10303-21; 908 | -------------------------------------------------------------------------------- /CAD/Clock_Shaft_Support.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/CAD/Clock_Shaft_Support.stl -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bryn Dole 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Weasley Clock 2 | 3 | Build a working physical [Weasley 4 | Clock](https://harrypotter.fandom.com/wiki/Weasley_Clock) from Harry 5 | Potter. 6 | 7 | Photo album of the build: 8 | 9 | Details of the build can be found in my [Build Log](BuildLog.md). 10 | 11 | ## Design 12 | 13 | ![Weasley Clock Flow Diagram](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/WeasleyClockDiagram.png) 14 | 15 | 16 | 1. Track location of family members using the Apple iCloud integration 17 | in HomeAssistant. This service allows for real-time 18 | updates of each family member's location and speed. HomeAssistant allows 19 | for naming of arbitrary geo-fenced areas. This is used for labeling 20 | locations like school and work. I might switch over to using Traccar at some point to get 21 | better reporting on movement. The initial implementation used life360, but 22 | they locked out any external access to their API, breaking the HomeAssistant 23 | integration. 24 | 25 | 2. Use [Home Assistant](https://www.home-assistant.io/) as a clearing 26 | house for family member location and movement within and around 27 | home. Home assistant is hosted on a Raspberry Pi 28 | running [Hass.io](https://www.home-assistant.io/hassio/). 29 | 30 | 3. Custom Home Assistant rules calculate the Weasley Clock state for 31 | each family member. Each state is visible from the Home Assistant 32 | dashboard. Changes in clock state are transmitted to the physical 33 | clock using the MQTT protocol over the network. 34 | 35 | 4. [Custom software](https://github.com/randomstring/weasleyclockd) 36 | running on a Raspberry Pi monitoring the MQTT message stream for 37 | changes in clock state and updating the physical clock hands to 38 | match. This software also adds some flare to hand movement. For 39 | example, the placement of the hand within each clock face sector 40 | will be determined by the person's distance from home. This way you 41 | can tell if someone is far or near to home at a glance. You might 42 | even be able to notice the progress of the person's clock hand 43 | progressing towards home. 44 | 45 | 5. A physical clock with four hands. The clock is mounted into an old 46 | grandfather clock. The face of the clock is divided into eight 47 | nearly equal sectors. Each sector has a location/situations 48 | label. These labels are: Home, Mortal Peril, Quidditch, Work, 49 | School, Garden, In Transit, and Lost. 50 | 51 | 6. The next phase will be to reuse the chimes that came with the 52 | original clock. The chimes can alert to noteworthy changes in the 53 | clock's state, for example, announcing someone's arrival back 54 | home. The current plan is to use a stepper motor to drive the 55 | existing chime mechanism. 56 | 57 | ## Clock Face and Meaning of Sectors 58 | 59 | ![Weasley Clock Demo 3](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/demo3.gif) ![Weasley Clock Demo 2](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/demo2.gif) 60 | 61 | What each sector of the clock face means: 62 | 63 | * **Home** The home state is triggered by the Home Assistant Apple iCloud 64 | integration. I have a defined geo-fenced area, when we are inside 65 | that region, we are considered home. I also use the Home Assistant 66 | Unifi integration to identify when members of the family are 67 | connected to the home WiFi network. Additionally, I can identify 68 | which WiFi access points (APs) they are connected to. This provides 69 | some granularity as to where they on the property. The system can 70 | tell if someone is in the shop, in the main house, or outside in the 71 | garden. I use the clockwise half of the Home sector to indicate 72 | someone is in the main house and the counter-clockwise half to 73 | indicate someone is in the shop. 74 | 75 | * **Lost** This is a catch-all state for when someone is stationary, 76 | not at home, and is not at one of the named locations of School or 77 | Work. The clock hand varies its location within the sector 78 | depending on how far from home they are. The closer to home, the 79 | closer the hand inches towards the Home sector. The position within 80 | the Lost sector varies on a logarithmic scale to give a finer 81 | grain detail when closer to home. 82 | 83 | * **In Transit** This indicates the family member is on the move. 84 | 85 | * **Garden** This sector is triggered when connecting to the WiFi 86 | access point outside, near the garden. 87 | 88 | * **School** Triggered when at a location labeled as "school." 89 | 90 | * **Work** Triggered when at a location labeled as "work." 91 | 92 | * **Quidditch** Triggered when someone is bicycling. I have this 93 | triggered in two ways. First, by a complex set of rules about low 94 | speed movement, faster than walking and slower than 95 | driving. Secondly, I detect when someone is currently active on 96 | [Zwift](https://zwift.com/), an VR indoor cycling app. 97 | 98 | * **Mortal Peril** This is triggered if the tracker measures someone's 99 | speed as greater than 75mph. With teenagers on the verge of driving 100 | age, I will be watching this one closely. 101 | 102 | 103 | ## Case Design 104 | 105 | I decided to reuse an old grandfather/grandmother clock instead of 106 | building a new case. I got lucky and found a perfect case at a thrift 107 | shop. The clock was a petite grandfather clock, sometimes referred to 108 | as a grandmother clock. Not as imposing and difficult to move as a 109 | full sized grandfather clock. I needed the dimensions of the face to 110 | match the artwork I have and the depth of the case needed to hold the 111 | servos and new clockwork. 112 | 113 | ## Clock Hands 114 | 115 | Hands are 3D printed with the name of each family member on the hands, 116 | just like in the Harry Potter movies. The bottom of each hand has the 117 | person's initial. Hands are painted for better contrast and to give an 118 | aged appearance. 119 | 120 | I spent a long time trying to figure out how to secure the hands to 121 | the brass tube axles. I considered clamping hubs (too bulky), collets 122 | (metal connectors traditional clock hands use), glue, and hot glue 123 | (this works well). In the end, by making the holes in the 3D printed 124 | hands strategical smaller, I was able to expand the holes with a file 125 | so that they just fit. They were tight enough to be secure. I did 126 | remove too much material from one of the hands and resorted to glue 127 | (E-6000) to keep it in place. 128 | 129 | Here are the [fonts](fonts/Fonts.md) I evaluated for use on the hands. 130 | 131 | ## Related Projects and Inspiration 132 | 133 | Over the course of this build I spent a fair amount of time 134 | researching how others have attempted to build a Weasley Clock. The 135 | most complete and authentic build I've found is by [Printable 136 | Props](https://www.instagram.com/printableprops/). 137 | 138 | - 139 | - 140 | - 141 | - 142 | - 143 | - 144 | - 145 | - 146 | - 147 | - 148 | - 149 | - 150 | - 151 | - 152 | - 153 | - 154 | - 155 | - 156 | 157 | ## Artwork 158 | 159 | I looked around on the internet and there are two styles of faces for 160 | the Weasley clock that appear in the Harry Potter movies. The first 161 | style comes up more often, and it is easier to replicate. It also has 162 | some sectors like "Prison" that I hope to never need. 163 | 164 | ![Weasley Clock Style 1](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/Weasley_clock_style1.gif) 165 | 166 | I prefer the second style. 167 | 168 | ![Weasley Clock Style 1](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/Weasley_clock_style2.jpg) 169 | 170 | As luck would have it, [Minalima](https://minalima.com/), the artists 171 | of this style, sell officially licensed [posters of the Weasley 172 | Clock](https://minalima.com/product/the-weasley-family-clock/). This 173 | was well worth the money for the poster as I didn't have to create the 174 | artwork myself and this *is* the artwork from the Harry Potter movie. 175 | 176 | ## Chimes 177 | 178 | The grandmother/grandfather clock came with a set of chimes. I plan to 179 | integrate them once I have the clock mechanism finished. I started a new project to research and document this build: [Weasley Chimes](https://github.com/randomstring/WeasleyChimes/). 180 | 181 | 182 | ## Home Assistant 183 | 184 | I am using [Home Assistant]() for 185 | tracking and transmitting the location of my family members. To do 186 | this I am using the [Apple iCloud 187 | integration]() for 188 | detailed location tracking. For tracking finer locations around the 189 | house I am using the [Unifi 190 | integration]() to 191 | monitor which WiFi access point each family member is closest to. 192 | 193 | ![Home Assistant Weasley Clock](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/homeassistant.png) 194 | 195 | I'm including example Home Assistant YAML configuration code creating 196 | a Weasley Clock sensor. This sensor will track a given user's Weasley 197 | Clock states: home, garden, school, work, intransit, mortalperil, lost, error. 198 | 199 | Example Home Assistant configurations can be found in the 200 | homeassistant directory. 201 | * [automations.yaml](homeassistant/automations.yaml) 202 | * [sensors.yaml](homeassistant/sensors.yaml) 203 | 204 | 205 | ## Software 206 | 207 | I need a daemon running on the Raspberry Pi that controls the clock 208 | servos. For this I 209 | wrote [weasleyclockd](https://github.com/randomstring/weasleyclockd) 210 | that monitors the MQTT messages from Home Assistant and manages the 211 | physical clock movement. 212 | 213 | 214 | ## CAD Models of Parts 215 | 216 | Most of the parts from ServoCity.com have CAD models that can be found 217 | here: 218 | 219 | CAD model of the HS-785HB Servo can be found here: 220 | 221 | 222 | Custom CAD files for the clock supports and hands are in the 223 | [CAD](CAD) sub-directory. 224 | 225 | The CAD for the clockworks support structures were created by my 226 | father-in-law, Ron. He also handled all the 3D printing for this 227 | project. 228 | 229 | My son, Alex, did the CAD for the clock hands, and generated a CAD 230 | rendering of the clockworks. Complete [CAD renderings of the clockworks 231 | and hands are on GrabCad.com](https://grabcad.com/library/weasley-clock-2). 232 | 233 | ![Cad View](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/CAD_Clock_Assembly.PNG) 234 | ![CAD Front View](https://raw.githubusercontent.com/randomstring/WeasleyClock/master/images/CAD_Clock_Assembly_Front.PNG) 235 | 236 | 237 | ## Mounting poster to plywood 238 | 239 | I used 3M Super 77 Spray Adhesive for mounting the clock face artwork. 240 | 241 | I had considered using [Mod 242 | Podge](https://www.amazon.com/Mod-Podge-CS11303-Waterbase-Sealer/dp/B0009ILH8C/) 243 | and went so far as experiment mounting some other posters to plywood 244 | using Mod Podge. 245 | 246 | 3M Super 77 leaves the face surface smoother, and doesn't require 247 | coating the front of the art to get good adhesion. Super 77 sets up 248 | really quickly, so watch some videos on how to use it and get a buddy 249 | to help keep the poster straight as you lay it down. 250 | 251 | 252 | # Shopping list 253 | 254 | ## Raspberry Pi 255 | 256 | - standard set of Raspberry pi requirements. Pi, power supply, SD card, case 257 | 258 | ## Servo Hat 259 | 260 | - Raspberry Pi servo hat: 261 | - requires soldering 262 | - Servo power, one of: 263 | - 5V 2A should be enough if motors aren't overloaded simultaneously 264 | - 5V 4A to hedge bets, or if you run more servos 265 | 266 | ## Shopping list from Servo City 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 |
CountDescriptionSKU
4HS-785HB SERVO33785S
332T, 0.250" (1/4) Bore 32P Shaft Mount Pinion Gear615254
132P, 32 Tooth, 24T C1 Spline Servo Mount Gear (Metal)615290
3C1 SPLINE SERVO TO 1/4" SHAFT COUPLER (SET SCREW)525134
30.250" (1/4") X 2.50" (2-1/2") STAINLESS STEEL D-SHAFTING634074
432 Pitch, 64 Tooth (.50" Bore) Aluminum Hub Gear615194
26mm (0.770") Clamping Hub545616
25mm (0.770") Clamping Hub545612
24MM (0.770") Clamping Hub545608
23MM (0.770") Clamping Hub545604
357 | 358 | ## Shopping list from Hobbylinc 359 | 360 | - 361 | - NOTE: checked items are a good set for a 4 hand clock. Theoretically 362 | possible to create a 6 hand clock with all of the sizes. However, 363 | servocity doesn't sell clamping hubs for size 2mm and 7mm. 364 | - parts: 365 | - [ ] 2mm x 300mm Round Brass Tube .45mm Wall (4) k+s9820 Item # K+S9820 366 | - [X] 3mm x 300mm Round Brass Tube .45mm Wall (4) k+s9821 Item # K+S9821 367 | - [X] 4mm x 300mm Round Brass Tube .45mm Wall (3) k+s9822 Item # K+S9822 368 | - [X] 5mm x 300mm Round Brass Tube .45mm Wall (3) k+s9823 Item # K+S9823 369 | - [X] 6mm x 300mm Round Brass Tube .45mm Wall (2) k+s9824 Item # K+S9824 370 | - [ ] 7mm x 300mm Round Brass Tube .45mm Wall (2) k+s9825 Item # K+S9825 371 | 372 | -------------------------------------------------------------------------------- /fonts/Fonts.md: -------------------------------------------------------------------------------- 1 | # Harry Potter Fonts 2 | 3 | I found these Marauders Map style fonts. This is as good a place as 4 | any to keep them for some future use. 5 | 6 | * ($45) 7 | * ($25) 8 | * ($36 for several fonts) 9 | 10 | 11 | # Fonts closely matching that of the Weasley Clock art 12 | 13 | It turns out this first batch of fonts are all Serif, not good for clock hands. 14 | 15 | * Morva 16 | * GiambattistaVsPetit 17 | * Modoni xt 18 | * Orgreave 19 | 20 | 21 | These following are San-Serif, and have a better chance at working in the clock hands. 22 | 23 | * Belleza (Used this one!) 24 | * Baar Sophia 25 | * Dumbledor 26 | * 27 | * 28 | * 29 | * 30 | 31 | Gothic fonts for the Initial 32 | * https://www.fontspace.com/black-initial-text-font-f10028 (used this one) 33 | * https://www.fontspace.com/deutsch-gothic-font-f9877 (and this one) 34 | * https://www.fontspace.com/dumbledor-font-f4911 35 | * https://www.fontspace.com/aneirin-font-f1960 36 | * https://www.fontspace.com/alpine-font-f1948 37 | * https://www.fontspace.com/gourdie-gothic-black-font-f7450 38 | * https://www.fontspace.com/blackwood-castle-font-f1977 39 | * https://www.fontspace.com/wellsley-font-f9906 40 | * https://www.fontspace.com/canterbury-font-f1984 (hard to 3d print?) 41 | 42 | -------------------------------------------------------------------------------- /fonts/acceptance_letter_by_decat_d55a2am.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/fonts/acceptance_letter_by_decat_d55a2am.ttf -------------------------------------------------------------------------------- /homeassistant/automations.yaml: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # Home Assistant Automation for publishing chages to Weasley Clock state 4 | # via MQTT. Includes the latitude and longitude of the user so that the 5 | # Weasley clock can adjust the location of the hands based on how far the 6 | # user is from home or maybe implement a seperate dial. 7 | # 8 | # Updates are sent when the user's state changes and when the 9 | # weasleyclockd process connects to the Home Assistant MQTT server. 10 | # When weasleyclockd connects it sends an "UPDATE" message. This also 11 | # triggers an update. 12 | # 13 | - id: '001' 14 | alias: Weasley Clock User1 15 | description: Send MQTT updates for changes in Weasley Clock state 16 | trigger: 17 | - entity_id: sensor.weasley_clock_user1 18 | platform: state 19 | - platform: mqtt 20 | topic: weasleyclock/UPDATE 21 | - event: start 22 | platform: homeassistant 23 | condition: [] 24 | action: 25 | - data: 26 | payload_template: '{"state":"{{ states("sensor.weasley_clock_user1") }}","latitude":"{{ 27 | state_attr("device_tracker.life360_user1", "latitude" )}}","longitude":"{{ 28 | state_attr("device_tracker.life360_user1", "longitude")}}"}' 29 | topic: weasleyclock/user1 30 | service: mqtt.publish 31 | -------------------------------------------------------------------------------- /homeassistant/configuration.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Proximity Integration 3 | # 4 | # 5 | # Track distance of each user from home. Use meters as units so the 6 | # value updates frequently. We depend on updates to trigger sensor 7 | # updates. Distance is in whole numbers, so using kilometers or miles 8 | # as units will lower the update frequency. 9 | # 10 | # https://www.home-assistant.io/integrations/proximity/ 11 | # 12 | 13 | proximity: 14 | user1: 15 | devices: 16 | - device_tracker.life360_user1 17 | tolerance: 50 18 | unit_of_measurement: m 19 | user2: 20 | devices: 21 | - device_tracker.life360_user2 22 | tolerance: 50 23 | unit_of_measurement: m -------------------------------------------------------------------------------- /homeassistant/gmailAutoarchive.js: -------------------------------------------------------------------------------- 1 | function gmailAutoarchive() { 2 | 3 | var delayMinutes = 15; // will only impact emails more than 15 minutes old 4 | var delayMilliseconds = delayMinutes * 60 * 1000; 5 | var maxTime = new Date().getTime() - delayMilliseconds; 6 | 7 | // Get first 100 threads from Inbox 8 | var threads = GmailApp.getInboxThreads(0, 100) 9 | 10 | // we archive all the threads older than the limit we set in delayMinutes 11 | for (var i = 0; i < threads.length; i++) { 12 | if (threads[i].getLastMessageDate().getTime() < maxTime) 13 | { 14 | threads[i].moveToArchive(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /homeassistant/sensors.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Sensor Tracks the name of home WiFi Access Point (AP) 3 | # 4 | # This uses the unifi integration to query the unifi APs for their state. 5 | # 6 | 7 | - platform: template 8 | sensors: 9 | home_ap_user1: 10 | entity_id: device_tracker.iphone 11 | value_template: >- 12 | {% set ap_mac_map = { 13 | 'DinningInWall': '78:8A:20:00:00:00', 14 | 'DownstairsAP': 'FC:EC:DA:00:00:00', 15 | 'GardenAP': 'FC:EC:DA:01:00:00' 16 | } -%} 17 | {%- set tracker = 'device_tracker.user1_phone' %} 18 | {%- set ns = namespace(ap='unknown') %} 19 | {%- if not is_state( tracker ) %} 20 | {%- set ns.ap = 'away' %} 21 | {%- else %} 22 | {%- set mac = state_attr( tracker , 'ap_mac').upper() %} 23 | {%- for ap, ap_mac in ap_mac_map.items() %} 24 | {%- if ap_mac == mac %} 25 | {%- set ns.ap = ap -%} 26 | {%- endif %} 27 | {%- endfor %} 28 | {%- endif %} 29 | {{ ns.ap }} 30 | 31 | # 32 | # Sensor produces Weasley Clock states 33 | # 34 | # home, garden, school, work, intransit, mortalperil, lost, error 35 | # 36 | # home/school/work/lost/intransit/lost is determined by life360 location 37 | # garden is based on which of the home WiFi access points is being used 38 | # mortalperil is triggered by life360 detecting speeds over 75 39 | # error is triggered if the life360 device_tracker returns None type 40 | # 41 | - platform: template 42 | sensors: 43 | weasley_clock_user1: 44 | entity_id: 45 | - sensor.home_ap_user1 46 | - proximity.user1 47 | - device_tracker.life360_user1 48 | icon_template: >- 49 | {% set icon = 'mdi:clock-outline' %} 50 | {% set s = 'sensor.weasley_clock_user1' %} 51 | {% if states(s) == 'school' %} 52 | {% set icon = 'mdi:school' %} 53 | {% elif states(s) == 'home' %} 54 | {% set icon = 'mdi:home' %} 55 | {% elif states(s) == 'barn' %} 56 | {% set icon = 'mdi:barn' %} 57 | {% elif states(s) == 'lost' %} 58 | {% set icon = 'mdi:map-marker-question' %} 59 | {% elif states(s) == 'intransit' %} 60 | {% set icon = 'mdi:train-car' %} 61 | {% elif states(s) == 'work' %} 62 | {% set icon = 'mdi:briefcase' %} 63 | {% elif states(s) == 'garden' %} 64 | {% set icon = 'mdi:flower' %} 65 | {% elif states(s) == 'mortalperil' %} 66 | {% set icon = 'mdi:speedometer' %} 67 | {% elif states(s) == 'quidditch' %} 68 | {% set icon = 'mdi:broom' %} 69 | {% endif %} 70 | {{ icon }} 71 | value_template: >- 72 | {%- set home_ap_sensor = 'sensor.home_ap_user1' %} 73 | {%- set tracker = 'device_tracker.life360_user1' %} 74 | {%- set ns = namespace(wc='lost') %} 75 | {%- set state = states( tracker ) %} 76 | {%- if not state %} 77 | {%- set ns.wc = 'error' %} 78 | {%- elif state == 'home' %} 79 | {%- set home_ap = states( home_ap_sensor ) %} 80 | {%- if home_ap == 'GardenAP' %} 81 | {%- set ns.wc = 'garden' -%} 82 | {%- else %} 83 | {%- set ns.wc = 'home' -%} 84 | {%- endif %} 85 | {%- elif state == 'moving' or state == 'driving' %} 86 | {%- set ns.wc = 'intransit' %} 87 | {%- set speed = state_attr( tracker, 'speed') %} 88 | {%- if speed and speed > 75 %} 89 | {%- set ns.wc = 'mortalperil' %} 90 | {%- endif %} 91 | {%- else %} 92 | {%- set place = state.lower() %} 93 | {%- if place == 'your local high school' or place == 'your local middle school'%} 94 | {%- set ns.wc = 'school' %} 95 | {%- elif place == 'work' %} 96 | {%- set ns.wc = 'work' %} 97 | {%- else %} 98 | {%- set ns.wc = 'lost' %} 99 | {%- endif %} 100 | {%- endif -%} 101 | {{ ns.wc }} 102 | -------------------------------------------------------------------------------- /images/CAD_Clock_Assembly.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/CAD_Clock_Assembly.PNG -------------------------------------------------------------------------------- /images/CAD_Clock_Assembly_Front.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/CAD_Clock_Assembly_Front.PNG -------------------------------------------------------------------------------- /images/CAD_servo_support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/CAD_servo_support.png -------------------------------------------------------------------------------- /images/CAD_shaft_support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/CAD_shaft_support.png -------------------------------------------------------------------------------- /images/ClockHands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/ClockHands.png -------------------------------------------------------------------------------- /images/PrintableProps_Hands.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/PrintableProps_Hands.jpg -------------------------------------------------------------------------------- /images/WeasleyClockDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/WeasleyClockDiagram.png -------------------------------------------------------------------------------- /images/WeasleyClockFace.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/WeasleyClockFace.jpeg -------------------------------------------------------------------------------- /images/Weasley_clock_style1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/Weasley_clock_style1.gif -------------------------------------------------------------------------------- /images/Weasley_clock_style2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/Weasley_clock_style2.jpg -------------------------------------------------------------------------------- /images/Weasleyclock_motd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/Weasleyclock_motd.png -------------------------------------------------------------------------------- /images/demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/demo2.gif -------------------------------------------------------------------------------- /images/demo3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/demo3.gif -------------------------------------------------------------------------------- /images/homeassistant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomstring/WeasleyClock/690b554c50281a0b32327589ec62386bbca3d1fb/images/homeassistant.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | adafruit-circuitpython-servokit 2 | --------------------------------------------------------------------------------