From 95836d6a5257d135273e87b17cb8d584e4281874 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Mon, 20 May 2024 23:38:42 +0100 Subject: [PATCH 1/7] Pull over some GitBuilding content from example documentation repo --- documentation/PeliCalse1430.md | 20 +++++++ documentation/README.md | 31 +--------- documentation/_templates/header.html.jinja | 15 +++++ documentation/assets/favicon-16x16.png | Bin 0 -> 926 bytes documentation/assets/favicon-32x32.png | Bin 0 -> 1824 bytes documentation/assets/favicon.ico | Bin 0 -> 152126 bytes documentation/assets/style.css | 19 ++++++ documentation/assets/wakoma-logo.png | Bin 0 -> 9706 bytes documentation/buildconf.yaml | 61 +++++++++---------- documentation/case.md | 38 ++++++++++++ documentation/components.md | 28 --------- documentation/config.md | 11 ++++ documentation/construction.md | 66 +++++++++++++++++++++ documentation/fasteners.yaml | 24 -------- documentation/finalize.md | 0 documentation/frame.md | 33 ----------- documentation/index.md | 33 ++++++----- documentation/knowledgebase.md | 5 ++ documentation/poe-explanation.md | 11 ++++ documentation/printing.md | 25 ++++++++ documentation/setup.md | 30 ++++++++++ documentation/tools.yaml | 15 ----- documentation/troubleshooting.md | 3 + documentation/wiring.md | 25 ++++++++ 24 files changed, 320 insertions(+), 173 deletions(-) create mode 100644 documentation/PeliCalse1430.md create mode 100644 documentation/_templates/header.html.jinja create mode 100644 documentation/assets/favicon-16x16.png create mode 100644 documentation/assets/favicon-32x32.png create mode 100644 documentation/assets/favicon.ico create mode 100644 documentation/assets/style.css create mode 100644 documentation/assets/wakoma-logo.png create mode 100644 documentation/case.md delete mode 100644 documentation/components.md create mode 100644 documentation/config.md create mode 100644 documentation/construction.md delete mode 100644 documentation/fasteners.yaml delete mode 100644 documentation/finalize.md delete mode 100644 documentation/frame.md create mode 100644 documentation/knowledgebase.md create mode 100644 documentation/poe-explanation.md create mode 100644 documentation/printing.md create mode 100644 documentation/setup.md delete mode 100644 documentation/tools.yaml create mode 100644 documentation/troubleshooting.md create mode 100644 documentation/wiring.md diff --git a/documentation/PeliCalse1430.md b/documentation/PeliCalse1430.md new file mode 100644 index 0000000..d5e0900 --- /dev/null +++ b/documentation/PeliCalse1430.md @@ -0,0 +1,20 @@ +--- +PartData: + Specs: + Internal Dimensions: 360 x 162 x 295 mm + Internal Lid Depth: 50 mm + Internal Base Depth: 245 mm + External Dimensions: 430 x 244 x 341 mm + Weight Empty: 2.54 kg + Weight With Foam: 2.95 kg + IP rating: IP67 + Airline carry on size?: True + Suppliers: + Peli Products: + PartNo: 1430-001-110 + Link: https://peliproducts.co.uk/products/1430-protector-case +--- + +# Peli Case 1430 + +To print the nimble you will need a fused filament fabrication (FFF) 3D printer, sometimes called a FDM printer. Most FDM printers should do. \ No newline at end of file diff --git a/documentation/README.md b/documentation/README.md index 4921067..6ea8c4d 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,30 +1,5 @@ - +This directory contains fixed documentation for all nimble racks and the templates that will be used by our orchestration script to generate complete documentation for any custom rack. -# This project is documented with GitBuilding - -## What is GitBuilding - -GitBuilding is an OpenSource project for documenting hardware projects with minimal -effort, so you can stop writing and GitBuilding. GitBuilding is a python program that -works on Windows, Linux, and MacOS. More information on the GitBuilding project, or how -to install GitBuilding please see the [GitBuilding website](http://gitbuilding.io) - -## How do I edit the documentation? - -To edit the documentation you do not need to install anything, but you will need to -install something to build the final version of the documentation (such as a website). -The documentation files can be opened in a plain text editor such as Windows Notepad, -Notepad++, gedit, VS Code, etc. GitBuilding also comes with a browser-based editor that -displays has a live display of the final HTML documentation. - -If you have ever used [markdown](https://www.markdownguide.org/basic-syntax/) you will -notice that the files you are editing are markdown files. GitBuilding uses an extended -markdown syntax (that we call BuildUp). This allows you to keep track of parts in the -documentation. More detail on the documentation is available on the -[GitBuilding website](https://gitbuilding.io/syntax/). There is also additional -[syntax for configuration](https://gitbuilding.io/syntax/buildconfsyntax), and for -[part libraries](https://gitbuilding.io/syntax/builduplibrary/). +As these scripts are not yet complete please see our [example documentation repository](https://github.com/Wakoma/nimble-example-documentation). diff --git a/documentation/_templates/header.html.jinja b/documentation/_templates/header.html.jinja new file mode 100644 index 0000000..7e0af23 --- /dev/null +++ b/documentation/_templates/header.html.jinja @@ -0,0 +1,15 @@ +
+{% if title is not none %} + +

{{title}}

+{%endif %} +{% if subtitle is not none %} +

{{subtitle}}

+{%endif %} +{% if authors is not none %} +

by {{authors}}

+{%endif %} +{% if affiliation is not none %} +

{{affiliation}}

+{%endif %} +
diff --git a/documentation/assets/favicon-16x16.png b/documentation/assets/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..6544b2f67871408056f499b331964b4c366ab92b GIT binary patch literal 926 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 O0000y9*-Wv*H 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 literal 0 HcmV?d00001 diff --git a/documentation/assets/style.css b/documentation/assets/style.css new file mode 100644 index 0000000..93978b4 --- /dev/null +++ b/documentation/assets/style.css @@ -0,0 +1,19 @@ + + +.wakoma-logo{ + width:60%; +} + +.wakoma-logo-link{ + line-height: 0.5; +} + +.site-title { + color: #424242; + font-size: 32px; + font-weight: 400; + line-height: 54px; + letter-spacing: -1px; + margin-bottom: 0; + display: flex; +} diff --git a/documentation/assets/wakoma-logo.png b/documentation/assets/wakoma-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c7182e5b946a0bb21b945dd1259aa7c3c44c5d7f GIT binary patch literal 9706 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 literal 0 HcmV?d00001 diff --git a/documentation/buildconf.yaml b/documentation/buildconf.yaml index dfbe156..8298523 100644 --- a/documentation/buildconf.yaml +++ b/documentation/buildconf.yaml @@ -1,31 +1,32 @@ - -Title: 'Nimble Rack' - -Authors: - - The Nimble team - -Affiliation: Wakoma - +AutoCompleteSubNav: true +CustomCategories: + consumable: + DisplayName: Comsumables + Reuse: false + mech: + DisplayName: Mechanical Components + Reuse: false + net: + DisplayName: Networking Compontents + Reuse: false + prev: + DisplayName: Previously Assembled + Reuse: false + printed: + DisplayName: 3D printed parts + Reuse: false +DefaultCategory: mech +HoverColor: '#555555' License: CERN-OHL-S-2.0 - -Email: info@wakoma.co - - -#Uncomment below to add custom categories -#CustomCategories: -# printedtool: -# Reuse: False -# DisplayName: Printed tools - -#Uncomment below to set a custom default category -#DefaultCategory: printedtool - -#Uncomment below to set the title for the bill of material on a page -#PageBOMTitle: '##For this step you will need' - - -#Uncomment below to set a custom Website root for static HTML builds -# WebsiteRoot: index.html - -#Uncomment below to disable fussy warnings -#Fussy: False +Navigation: + - Link: config.md + Title: Your Nimble Configuration + - Link: troubleshooting.md + Title: Troubleshooting + - Link: knowledgebase.md + Title: Knowledge Base +PageBOMTitle: '## For this page you will need' +PrimaryColor: '#2d3b46' +SecondaryColor: '#cccccc' +ExternalDirs: + project: ".." diff --git a/documentation/case.md b/documentation/case.md new file mode 100644 index 0000000..b6274ce --- /dev/null +++ b/documentation/case.md @@ -0,0 +1,38 @@ +--- +Make: + AP Mount Top: + template: printing.md + stl-file: ../Legacy/STLs/ap_mount_for_1430_top.stl + stlname: ap_mount_for_1430_top.stl + material: PLA + weight-qty: 40g + supports: "Yes" + AP Mount Bottom: + template: printing.md + stl-file: ../Legacy/STLs/ap_mount_for_1430_bottom.stl + stlname: ap_mount_for_1430_bottom.stl + material: PLA + weight-qty: 40g + supports: "Yes" +--- + +# Prepare the case + +{{BOM}} + +[M4x10mm countersunk screws]: parts/Hardware.yaml#CskScrew_M4x10mm_SS +[M4x10mm cap screws]: parts/Hardware.yaml#CapScrew_M4x10mm_SS + +## Construct the lid insert {pagestep} + +* Join [AP Mount Top]{make, qty:1,cat:printed} and [AP Mount Bottom]{make, qty:1,cat:printed} together using two [M4x10mm countersunk screws]{qty: 2,cat: mech} and a [3mm Allen key](parts/metric_allen_keys.md){qty: 1,cat: tool} +* Using three more [M4x10mm countersunk screws]{qty: 3,cat: mech} attach the brackets that came with your three UniFi Access Points to the holes just below the join between the two prints. + +## Attach to case{pagestep} + +* Get your [Peli Case][Peli Case 1430](PeliCalse1430.md){qty:1} and open the lid. +* Locate the mounting lugs on the peli case lid and align the lid insert with these lugs +* Use [M4x10mm cap screws]{qty: 2,cat: mech} to attach the inset into the Peli Case. + +>!! **TODO** +>!! Add images of this step diff --git a/documentation/components.md b/documentation/components.md deleted file mode 100644 index d5dff15..0000000 --- a/documentation/components.md +++ /dev/null @@ -1,28 +0,0 @@ - - -# Installing the components in trays - -{{BOM}} -![](svg/baseplate_beams_topplate.svg) - -For all of your components: - -* find the corresponding 3d printed tray -* install the tray on the rack -* mount the device on the tray - -Here are the devices and the trays - -* [Netgate SG-1100](DeviceParts.yaml#NetgateSG1100){Qty: 1} -* tray_NetgateSG1100.stl ([preview](models/tray_NetgateSG1100.stl){previewpage}, [download](models/tray_NetgateSG1100.stl)) -* [UniFi USW-Flex](DeviceParts.yaml#UniFiUSWFlex){Qty: 1} -* tray_UniFiUSWFlex.stl ([preview](models/tray_UniFiUSWFlex.stl){previewpage}, [download](models/tray_UniFiUSWFlex.stl)) -* [Intel NUC10i5FNH](DeviceParts.yaml#NUC10i5FNH){Qty: 1} -* tray_NUC10i5FNH.stl ([preview](models/tray_NUC10i5FNH.stl){previewpage}, [download](models/tray_NUC10i5FNH.stl)) -* [Raspberry Pi 4](DeviceParts.yaml#RPi4){Qty: 1} -* tray_RPi4.stl ([preview](models/tray_RPi4.stl){previewpage}, [download](models/tray_RPi4.stl)) -![](svg/trays.svg) diff --git a/documentation/config.md b/documentation/config.md new file mode 100644 index 0000000..d60b748 --- /dev/null +++ b/documentation/config.md @@ -0,0 +1,11 @@ +# Your Nimble Configuration + +The nimble is a modular rack-and-shelf system. The first part of construction is to 3D print the custom parts, and then to assemble the shelves. + +The shelves in your system are: + +{{listpages, tag:shelf}} + +Once you have assembled each shelf, you will [construct the rack](construction.md){step} and [prepare the case](case.md){step} before finally [wiring up the system](wiring.md){step} and [setting it up](setup.md){step}. + +Make sure you have [all the parts you need]{bom}, before you start assembly. \ No newline at end of file diff --git a/documentation/construction.md b/documentation/construction.md new file mode 100644 index 0000000..2a9c1be --- /dev/null +++ b/documentation/construction.md @@ -0,0 +1,66 @@ +--- +Make: + base plate: + template: printing.md + stl-file: ../build/printed_components/baseplate.stl + stlname: baseplate.stl + material: PLA + weight-qty: 50g + top plate: + template: printing.md + stl-file: ../build/printed_components/topplate.stl + stlname: topplate.stl + material: PLA + weight-qty: 50g + rack legs: + template: printing.md + stl-file: ../build/printed_components/beam.stl + stlname: beam.stl + material: PLA + weight-qty: 60g + stuff shelf: + template: printing.md + stl-file: models/Stuff_Shelf_1.0.stl + stlname: Stuff_Shelf_1.0.stl + material: PLA + weight-qty: 50g +--- + +# Construct the and populate the rack + +{{BOM}} + +[M4x10mm countersunk screws]: parts/Hardware.yaml#CskScrew_M4x10mm_SS +[M4x10mm cap screws]: parts/Hardware.yaml#CapScrew_M4x10mm_SS + +## Attach the legs to the base plate{pagestep} + +* Get the [base plate]{make, qty:1, cat:printed} and the four [rack legs]{make, qty:4, cat:printed} that you printed earlier. +* Get an [3mm Allen key](parts/metric_allen_keys.md){qty:1, cat:tool} ready +* Use four [M4x10mm countersunk screws]{qty:4} to attach a leg to each corner of the bottom. + +>!! **TODO** +>!! Add images of this step + +## Add the broad shelves {pagestep} + +>!! **TODO** +>!! Each shelf that is broad should be added in this stage + + +## Mount the top plate {pagestep} + +* Take the [top plate]{make, qty:1, cat:printed} and place it on top of the rack. +* Use four [M4x10mm countersunk screws]{qty:4} to attach the shelf to the four legs of the rack + +>!! **TODO** +>!! Add images of this step + + +## Insert the remaining shelves {pagestep} + +>!! **TODO** +>!! Explain what order the assembled shelves are used. + + + diff --git a/documentation/fasteners.yaml b/documentation/fasteners.yaml deleted file mode 100644 index d4f968c..0000000 --- a/documentation/fasteners.yaml +++ /dev/null @@ -1,24 +0,0 @@ - -M4x10PanSteel: - Name: M4x10 Pan Head Steel - Specs: - Head: Pan - Length: 10 mm - Material: Stainless Steel - Pitch: 0.7 - Suppliers: - RS: - PartNo: 528-817 - Link: https://uk.rs-online.com/web/p/machine-screws/0528817/ - McMasterCarr: - PartNo: 90116A207 - Link: https://www.mcmaster.com/90116A207 - -M5x8_DIN7991: - Name: M5x8 DIN 7991 Counter Sunk Screw - Specs: - Head: Counter Sunk / Flat Head - Size: M5 - Length: 8 mm - Pitch: Standard / 0.8 - Material: Stainless Steel diff --git a/documentation/finalize.md b/documentation/finalize.md deleted file mode 100644 index e69de29..0000000 diff --git a/documentation/frame.md b/documentation/frame.md deleted file mode 100644 index 59286be..0000000 --- a/documentation/frame.md +++ /dev/null @@ -1,33 +0,0 @@ - - -[M5x8 screws]:fasteners.yaml#M5x8_DIN7991 -[Allen Key 3mm]:tools.yaml#Allen_3mm - -# Assembling the frame - -{{BOM}} - -## Start with the base plate {pagestep} - -* Start with the [3d printed base plate](3DPParts.yaml#baseplate){Qty: 1} - -![](svg/baseplate.svg) - -## Add beams {pagestep} - -* Add a [3d printed beam](3DPParts.yaml#beam){Qty: 4} at each corner -* Use [M5x8 screws]{Qty: 4} and screw them together - -![](svg/baseplate_beams.svg) - -## Add top plate {pagestep} - -* Add [3d printed top plate](3DPParts.yaml#topplate){Qty: 1} -* Use [M5x8 screws]{Qty: 4} and screw it on the beams - -![](svg/baseplate_beams_topplate.svg) - diff --git a/documentation/index.md b/documentation/index.md index 9f6d604..8da84b9 100644 --- a/documentation/index.md +++ b/documentation/index.md @@ -1,28 +1,31 @@ - -# Nimble Rack Assembly +## What is Nimble -The Nimble rack is built from 3d printed parts. There are some standard components, as well as custom trays for all the networking devices that you are using. +Nimble is an open source, rapidly deployable, wireless mesh network. -This is a [list of needed parts]{BOM} -As a first step you need to 3d print the needed parts +![](../assets/img/2-23.jpg) -[.](3dprintingparts.md){step} +Anyone connected to the nimble can video and voice chat, stream videos, share files, build and run eLearning courses and website, create collaborative spreadsheets and documents, read e-books, play games, and so much more… completely offline. -Assembly starts with the frame: +If a single internet connection is available, it can be plugged into the nimble to provide free or paid internet access to anyone on the network. The offline services and content are always available to users, regardless of internet availability. -[.](frame.md){step} +Anyone in the world can build their own nimble with locally sourced hardware and 3D-printed components. -You then add the trays and the individual components to the frame: +You can find out more about Nimble on [our website](https://wakoma.co/nimble/). -[.](components.md){step} +## Customisation -The assembly is finished by doing the cabling and adding the battery +Nimble, as an open source project, is designed so that you can tailor it to your own needs and to the hardware that you have available. -[.](finalize.md){step} +![](../assets/img/Model_M/1.jpg) +We are [working on building a an interface for customising your nimble](https://github.com/Wakoma/nimble/pull/23). In the mean time this is an example of the assembly instructions for a specific configuration. + +To customise your Nimble you can go to [our GitHub](https://github.com/Wakoma/nimble). If you aren't sure where to start, you can always ask for help by [opening an issue](https://github.com/Wakoma/nimble/issues) or [starting a discussion](https://github.com/Wakoma/nimble/discussions). + +## Building your Nimble + +In the next pages we will build [your nimble](config.md){step}. diff --git a/documentation/knowledgebase.md b/documentation/knowledgebase.md new file mode 100644 index 0000000..24d3119 --- /dev/null +++ b/documentation/knowledgebase.md @@ -0,0 +1,5 @@ +# Nimble Knowledge Base + +The following pages may help you understand your Nimble. + +{{listpages, tag:info}} \ No newline at end of file diff --git a/documentation/poe-explanation.md b/documentation/poe-explanation.md new file mode 100644 index 0000000..0402486 --- /dev/null +++ b/documentation/poe-explanation.md @@ -0,0 +1,11 @@ +--- +Tags: info +--- + +# Power over Ethernet + +Many of the devices in your Nimble are powered directly through the Ethernet cable. + +Power over Ethernet allows both data and power to be transmitted between devices using only a single cable. This really cuts down on excess cables. + +There is far more information on Power over Ethernet at [wikipedia](https://en.wikipedia.org/wiki/Power_over_Ethernet) \ No newline at end of file diff --git a/documentation/printing.md b/documentation/printing.md new file mode 100644 index 0000000..4077f27 --- /dev/null +++ b/documentation/printing.md @@ -0,0 +1,25 @@ +# 3D Printing + +{{BOM}} + +[PLA]:parts/filament.md "{cat:consumable}" + +## Print the custom components {pagestep} + + +Using the slicer that comes with your [3d printer](parts/3dprinter.md){qty:1, cat: tool}, slice thent the following parts, and then print them. + +Some parts require support. A brim is advised for all parts. + + +| Qty | Item | Material | File | Supports
Required?| +|-----|------|----------|------|----------------------| +{{foreachmakeitem: "| {{qty}} | {{id}} | {{weight-qty}} of [{{material}}]{qty:{{weight-qty}}} | [{{stlname}}]({{stl-file}}){previewpage}|{{supports, default: No}}|"}} + + +You can [download all of the STLs as a single zipfile](all-stls.zip){zip, pattern:"*.stl"} + + +## Remove the brim {pagestep} + +Remove the brim with a [utility knife](parts/utility_knife.md){qty:1, cat:tool} diff --git a/documentation/setup.md b/documentation/setup.md new file mode 100644 index 0000000..a3483f6 --- /dev/null +++ b/documentation/setup.md @@ -0,0 +1,30 @@ +# Set Up your Nimble + +>!! **TODO** +>!! +>!! * How do we power it on?! +>!! * Are there other set up steps!? + +{{BOM}} + + +## Mount the rack and access points{pagestep} + +* Take your wired Nimble rack and insert into your Peli Case. + + +>!! **TODO** +>!! Add images of this step + +* Take the three [UniFi Access Points](parts/UniFiAccessPoints.md){qty:3, cat:net} and clip them onto the mounting brackets in the Peli Case lid. + + +>!! **TODO** +>!! Add images of this step + +## Power on the system + + +>!! **TODO** +>!! Add images of this step + diff --git a/documentation/tools.yaml b/documentation/tools.yaml deleted file mode 100644 index 68562c8..0000000 --- a/documentation/tools.yaml +++ /dev/null @@ -1,15 +0,0 @@ - -Screwdriver_Philips_No2: - Name: No. 2 Phillips screwdriver - Description: > - No2 Phillips screwdriver. This is the correct size - form an M4 pan head screw - Specs: - Drive Size: No. 2 - -Allen_3mm: - Name: Allen Key 3mm - Description: > - Allen Key 3mm - Specs: - Drive Size: 3mm diff --git a/documentation/troubleshooting.md b/documentation/troubleshooting.md new file mode 100644 index 0000000..a99dcd1 --- /dev/null +++ b/documentation/troubleshooting.md @@ -0,0 +1,3 @@ +# Troubleshooting and Support + +**Write me!!** \ No newline at end of file diff --git a/documentation/wiring.md b/documentation/wiring.md new file mode 100644 index 0000000..a39f774 --- /dev/null +++ b/documentation/wiring.md @@ -0,0 +1,25 @@ +--- +Make: + Power Box: + template: printing.md + stl-file: ../Legacy/STLs/power_box.stl + stlname: power_box.stl + material: PLA + weight-qty: 60g +--- + +# Wiring The Nimble + +>!! **TODO** +>!! +>!! * Write the instructions +>!! * Be clear what passes through where +>!! * Add cables to the BOM.. what are they!? +>!! * Annotate images to be clear what we are looking at + +{{BOM}} + + +Once done must mention [Power Box]{make, qty:1,cat:printed} + + From c867f8dbb72556b887d85df92530a556fbb0965a Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Mon, 20 May 2024 23:39:35 +0100 Subject: [PATCH 2/7] Use GitBuilding alpha release for new functionality --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2d79755..78841b8 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ 'cadscript>=0.5.2', 'exsource-tools', 'cq-cli @ git+https://github.com/CadQuery/cq-cli.git', - 'gitbuilding' + 'gitbuilding==0.15.0a2' ], extras_require={ 'dev': [ From 2b21e43c4ada02f021cf977b9dadcb62d5e11462 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Tue, 21 May 2024 01:09:56 +0100 Subject: [PATCH 3/7] Configuration to better track shelves via Shelf object --- .gitignore | 3 ++ generate.py | 2 + mechanical/components/cadquery/tray_6in.py | 37 +++++++++----- nimble_orchestration/components.py | 37 +++++++++++++- nimble_orchestration/configuration.py | 56 ++++++++++++++-------- nimble_orchestration/device.py | 23 +++++++-- nimble_orchestration/orchestration.py | 16 ++++++- nimble_orchestration/paths.py | 2 + 8 files changed, 136 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 01c74fb..d137fd3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ _site/ +_gb_temp_/ build/ + + .vscode/* .venv/ __pycache__/ diff --git a/generate.py b/generate.py index 785aaf2..97fc2d6 100755 --- a/generate.py +++ b/generate.py @@ -26,6 +26,8 @@ def generate(selected_devices_ids): runner.generate_assembly(config.assembly_definition) + runner.generate_docs(config) + def generate_example_configuration(): """ diff --git a/mechanical/components/cadquery/tray_6in.py b/mechanical/components/cadquery/tray_6in.py index b5f20d2..4a90fe8 100644 --- a/mechanical/components/cadquery/tray_6in.py +++ b/mechanical/components/cadquery/tray_6in.py @@ -29,16 +29,11 @@ height_in_u = 2 -def create_6in_shelf(shelf_type, height_in_u) -> cad.Body: - """ - This is the top level function called when the script - is called. It uses the `shelf_type` string to decide - which of the defined shelf functions to call. - """ +def _shelf_functions(): # Dictionary of with key as shelf type and value as tuple # of (function, keyword-arguments) - shelf_functions = { + return { "generic": (generic_shelf, {}), "stuff": (stuff_shelf, {}), "stuff-thin": (stuff_shelf, {"thin":True}), @@ -69,11 +64,29 @@ def create_6in_shelf(shelf_type, height_in_u) -> cad.Body: "raspi": (raspi_shelf, {}) } - if shelf_type in shelf_functions: - shelf_func = shelf_functions[shelf_type][0] - kwargs = shelf_functions[shelf_type][1] - return shelf_func(height_in_u, **kwargs) - raise ValueError(f"Unknown shelf type: {shelf_type}") +def available_shelves(): + """ + Return a list of suported shelf-types. + """ + return list(_shelf_functions().keys) + +def create_6in_shelf(shelf_type, height_in_u) -> cad.Body: + """ + This is the top level function called when the script + is called. It uses the `shelf_type` string to decide + which of the defined shelf functions to call. + """ + + shelf_functions = _shelf_functions() + + if shelf_type not in shelf_functions: + print(f"Unknown shelf type: {shelf_type}, creating generic shelf") + shelf_type = "generic" + + shelf_func = shelf_functions[shelf_type][0] + kwargs = shelf_functions[shelf_type][1] + return shelf_func(height_in_u, **kwargs) + def generic_shelf(height_in_u) -> cad.Body: """ diff --git a/nimble_orchestration/components.py b/nimble_orchestration/components.py index f590496..d3d4792 100644 --- a/nimble_orchestration/components.py +++ b/nimble_orchestration/components.py @@ -10,7 +10,7 @@ `MechanicalComponent` """ from copy import copy, deepcopy - +from nimble_orchestration.device import Device class MechanicalComponent: """ @@ -168,3 +168,38 @@ def color(self): The color of this component. """ return self._color + + +class Shelf: + """ + A class for all the orchestraion information relating to a shelf + """ + def __init__(self, + assembled_shelf: AssembledComponent, + device: Device): + self._assembled_shelf = assembled_shelf + self._device = device + + @property + def assembled_shelf(self): + """ + Return the Object describing the assembled shelf (currently this in an empty + shelf in the correct location on the rack). + This is an AssembledComponent + """ + return self._assembled_shelf + + @property + def device(self): + """ + Return the Device object for the networking component that sits on this shelf + """ + return self._device + + @property + def md(self): + """ + Return the gitbuilding markdown for assembling this shelf + """ + + return f"# {self._device.name}\n\n This is a shelf for a {self._device.name}" \ No newline at end of file diff --git a/nimble_orchestration/configuration.py b/nimble_orchestration/configuration.py index 0f4eaaf..9e24fe2 100644 --- a/nimble_orchestration/configuration.py +++ b/nimble_orchestration/configuration.py @@ -12,7 +12,9 @@ from nimble_builder import RackParameters from nimble_orchestration.assembly_def_generator import AssemblyDefGenerator -from nimble_orchestration.components import GeneratedMechanicalComponent, AssembledComponent +from nimble_orchestration.components import (GeneratedMechanicalComponent, + AssembledComponent, + Shelf) from nimble_orchestration.device import Device from nimble_orchestration.paths import MODULE_PATH, REL_MECH_DIR @@ -22,6 +24,7 @@ class NimbleConfiguration: """ _rack_params: RackParameters _devices: list + _shelves: list _components: list _assembled_components: list @@ -40,6 +43,7 @@ def find_device(device_id): selected_devices = [Device(find_device(x)) for x in selected_devices_ids] self._devices = deepcopy(selected_devices) + self._shelves = self._generate_shelf_list self._assembled_components = self._generate_assembled_components_list() self._components = [] for assembled_component in self._assembled_components: @@ -78,6 +82,16 @@ def assembled_components(self): """ return deepcopy(self._assembled_components) + @property + def shelves(self): + """ + Return a list of the shelves assembled in this nimble rack. + + Each object in the list is and instance of Shelf object, this holds both the information on + the assembled shelf, and on the Device the shelf is for. + """ + return deepcopy(self._shelves) + @property def total_height_in_u(self): """ @@ -90,7 +104,7 @@ def _generate_assembled_components_list(self): # collect all needed parts and their parameters rack_components = self._legs + [self._baseplate, self._topplate] - return rack_components + self._trays + return rack_components + [i.assembled_shelf for i in self._shelves] @property def _legs(self): @@ -192,51 +206,51 @@ def _topplate(self): ) @property - def _trays(self): + def _generate_shelf_list(self): """ - Generate aseembled components for each tray. This function is a bit + Generate aseembled components for each shelf. This function is a bit long and messy! """ source = os.path.join(REL_MECH_DIR, "components/cadquery/tray_6in.py") source = posixpath.normpath(source) - trays = [] + shelves = [] z_offset = self._rack_params.bottom_tray_offet height_in_u = 0 for i, device in enumerate(self._devices): x_pos = 0 y_pos = -self._rack_params.rack_width / 2.0 z_pos = z_offset + height_in_u * self._rack_params.mounting_hole_spacing - tray_id = device.tray_id + shelf_key = device.shelf_key color = 'dodgerblue1' if i%2 == 0 else 'deepskyblue1' component = GeneratedMechanicalComponent( - key=tray_id, - name=f"{device.name} tray", - description="A tray for " + device.name, + key=shelf_key, + name=f"{device.name} shelf", + description="A shelf for " + device.name, output_files=[ - f"./printed_components/{tray_id}.step", - f"./printed_components/{tray_id}.stl", + f"./printed_components/{shelf_key}.step", + f"./printed_components/{shelf_key}.stl", ], source_files=[source], parameters={ "height_in_u": device.height_in_u, - "shelf_type": "generic", + "shelf_type": device.shelf_builder_id, }, application="cadquery" ) - trays.append( - AssembledComponent( - key=f"tray_{i}", - component=component, - position = (x_pos, y_pos, z_pos), - step=4, - color=color - ) + assm_component = AssembledComponent( + key=f"shelf_{i}", + component=component, + position = (x_pos, y_pos, z_pos), + step=4, + color=color ) + shelves.append(Shelf(assm_component, device)) + height_in_u += device.height_in_u - return trays + return shelves @property def assembly_definition(self): diff --git a/nimble_orchestration/device.py b/nimble_orchestration/device.py index 0f7aa8e..bb2bec9 100644 --- a/nimble_orchestration/device.py +++ b/nimble_orchestration/device.py @@ -2,6 +2,8 @@ Contains an object that represents the information of a device in the devices.json file. """ +import re + class Device: """ Represents a subset of the information for a device from the devices.json file @@ -48,12 +50,25 @@ def __init__(self, json_node): self.width = json_node['LengthMm'] self.depth = json_node['Depth'] self.shelf_id = json_node['ShelfId'] - # self.tray_type = json_node['TrayType'] self.shelf_type = json_node['Shelf'] @property - def tray_id(self): + def shelf_key(self): + """ + Return an key to identify the shelf. + """ + return f"shelf_h{self.height_in_u}_t{self.shelf_type.lower().replace(' ', '_')}" + + @property + def shelf_builder_id(self): """ - Return an identification for the shelf. + shelf_builder and devices.json don't key use the same ids. devices.json seems + to use similar terms but appends -6 as the shelf is 6 inch, and optionally -s + and -t for tall and short versions. + These should be unified later """ - return f"tray_h{self.height_in_u}_t{self.shelf_type.lower().replace(' ', '_')}" + if self.shelf_id: + if match := re.match(r'^(.*)-6(?:-[st])?$', self.shelf_id): + #strip of -6 and optionally -s or -t + return match.group(1) + return "generic" diff --git a/nimble_orchestration/orchestration.py b/nimble_orchestration/orchestration.py index 4cf8544..2896950 100644 --- a/nimble_orchestration/orchestration.py +++ b/nimble_orchestration/orchestration.py @@ -7,14 +7,14 @@ """ import os - +import shutil import exsource_tools import exsource_tools.cli import exsource_tools.tools from nimble_orchestration.exsource_def_generator import ExsourceDefGenerator -from nimble_orchestration.paths import BUILD_DIR, REL_MECH_DIR +from nimble_orchestration.paths import BUILD_DIR, REL_MECH_DIR, DOCS_DIR, DOCS_TMP_DIR class OrchestrationRunner: """ @@ -81,6 +81,18 @@ def generate_assembly(self, assembly_definition): exsource.save(exsource_path) self._run_exsource(exsource_path) + def generate_docs(self, configuration): + """ + Run GitBuilding to generate documentation + """ + if os.path.exists(DOCS_TMP_DIR): + shutil.rmtree(DOCS_TMP_DIR) + shutil.copytree(DOCS_DIR, DOCS_TMP_DIR) + + for shelf in configuration.shelves: + filename = os.path.join(DOCS_TMP_DIR, f"{shelf.device.id}_shelf.md") + with open(filename, 'w', encoding="utf-8") as gb_file: + gb_file.write(shelf.md) def _run_exsource(self, exsource_path): diff --git a/nimble_orchestration/paths.py b/nimble_orchestration/paths.py index 2834c76..1e1d3d9 100644 --- a/nimble_orchestration/paths.py +++ b/nimble_orchestration/paths.py @@ -7,3 +7,5 @@ MODULE_PATH = os.path.normpath(os.path.join(os.path.split(__file__)[0], '..')) BUILD_DIR = os.path.join(MODULE_PATH, "build") REL_MECH_DIR = os.path.relpath(os.path.join(MODULE_PATH, "mechanical"), BUILD_DIR) +DOCS_DIR = os.path.join(MODULE_PATH, "documentation") +DOCS_TMP_DIR = os.path.join(MODULE_PATH, "_gb_temp_") From 470dd226e5c155165795ac98d70b29c70b92bd0d Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Tue, 21 May 2024 01:23:33 +0100 Subject: [PATCH 4/7] Run Gitbuilding in generate.py --- nimble_orchestration/orchestration.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nimble_orchestration/orchestration.py b/nimble_orchestration/orchestration.py index 2896950..da1435b 100644 --- a/nimble_orchestration/orchestration.py +++ b/nimble_orchestration/orchestration.py @@ -8,6 +8,7 @@ import os import shutil +import subprocess import exsource_tools import exsource_tools.cli @@ -94,6 +95,23 @@ def generate_docs(self, configuration): with open(filename, 'w', encoding="utf-8") as gb_file: gb_file.write(shelf.md) + self._run_gitbuilding() + + def _run_gitbuilding(self): + cur_dir = os.getcwd() + os.chdir(DOCS_TMP_DIR) + ret = subprocess.run( + ['gitbuilding', 'build-html'], + check=True, + capture_output=True + ) + os.chdir(cur_dir) + tmp_built_docs = os.path.join(DOCS_TMP_DIR, "_site") + built_docs = os.path.join(BUILD_DIR, "assembly-docs") + if os.path.exists(built_docs): + shutil.rmtree(built_docs) + shutil.copytree(tmp_built_docs, built_docs) + def _run_exsource(self, exsource_path): cur_dir = os.getcwd() From ae28310425e4138c3dbe398e1b2439c4b23af537 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Tue, 21 May 2024 01:32:48 +0100 Subject: [PATCH 5/7] Run generate.py on CI to create gitbuilding docs. Add link to this on static index --- .github/workflows/publish.yml | 4 ++++ generate.md | 2 +- generate_static.py | 10 +++++++++- nimble_orchestration/components.py | 2 +- nimble_orchestration/orchestration.py | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3c20192..8c3bc19 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -45,6 +45,10 @@ jobs: run: | ./generate_static.py + - name: Generate example docs + run: | + ./generate.py + - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: diff --git a/generate.md b/generate.md index 3d9339f..6e9f00b 100644 --- a/generate.md +++ b/generate.md @@ -46,7 +46,7 @@ To run this script, run the following command: This should create the `build` directory. Inside this the `printed_components` directory should contain a number of `stl` files that can be 3D printed. -The script also creates a simple web-page with an index of all of the files. +The script also creates a simple web-page with an index of all of the files. The final link to the "Partially complete automatically generated documentation" will be broken unless you also run `generate.py` (see below). It also creates a number of files that are used by the orchestration script. diff --git a/generate_static.py b/generate_static.py index f95f7ef..6bf13df 100755 --- a/generate_static.py +++ b/generate_static.py @@ -150,7 +150,6 @@ def output_static_site(components): for hardware configuration. We call this "Smart Doc". For more details on Nimble see
https://github.com/Wakoma/nimble

-

Smart Doc" is not yet finished, but the code already generates a number of nimble components @@ -164,6 +163,15 @@ def output_static_site(components): for component in components: f.write(f"

  • {component.name}
  • ") f.write("") + f.write( + """ +

    Example documentation:

    +

    + Partially complete automatically generated documentation + is also available. +

    + """) + f.write("") if __name__ == "__main__": diff --git a/nimble_orchestration/components.py b/nimble_orchestration/components.py index d3d4792..13b5e09 100644 --- a/nimble_orchestration/components.py +++ b/nimble_orchestration/components.py @@ -202,4 +202,4 @@ def md(self): Return the gitbuilding markdown for assembling this shelf """ - return f"# {self._device.name}\n\n This is a shelf for a {self._device.name}" \ No newline at end of file + return f"# {self._device.name}\n\n This is a shelf for a {self._device.name}" diff --git a/nimble_orchestration/orchestration.py b/nimble_orchestration/orchestration.py index da1435b..80c1718 100644 --- a/nimble_orchestration/orchestration.py +++ b/nimble_orchestration/orchestration.py @@ -100,7 +100,7 @@ def generate_docs(self, configuration): def _run_gitbuilding(self): cur_dir = os.getcwd() os.chdir(DOCS_TMP_DIR) - ret = subprocess.run( + subprocess.run( ['gitbuilding', 'build-html'], check=True, capture_output=True From cd83cd2bfd5f11efef4eaecc8503c0ed17f65d59 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Tue, 21 May 2024 08:35:48 +0100 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Jeremy Wright --- .gitignore | 1 - documentation/case.md | 2 +- documentation/construction.md | 4 ++-- documentation/index.md | 4 ++-- documentation/poe-explanation.md | 2 +- documentation/printing.md | 2 +- documentation/setup.md | 6 +++--- documentation/wiring.md | 2 +- nimble_orchestration/components.py | 4 ++-- nimble_orchestration/configuration.py | 2 +- nimble_orchestration/device.py | 2 +- 11 files changed, 15 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index d137fd3..0f99dc4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ _site/ _gb_temp_/ build/ - .vscode/* .venv/ __pycache__/ diff --git a/documentation/case.md b/documentation/case.md index b6274ce..0c74cb8 100644 --- a/documentation/case.md +++ b/documentation/case.md @@ -31,7 +31,7 @@ Make: ## Attach to case{pagestep} * Get your [Peli Case][Peli Case 1430](PeliCalse1430.md){qty:1} and open the lid. -* Locate the mounting lugs on the peli case lid and align the lid insert with these lugs +* Locate the mounting lugs on the Peli Case lid and align the lid insert with these lugs * Use [M4x10mm cap screws]{qty: 2,cat: mech} to attach the inset into the Peli Case. >!! **TODO** diff --git a/documentation/construction.md b/documentation/construction.md index 2a9c1be..1d6b251 100644 --- a/documentation/construction.md +++ b/documentation/construction.md @@ -33,10 +33,10 @@ Make: [M4x10mm countersunk screws]: parts/Hardware.yaml#CskScrew_M4x10mm_SS [M4x10mm cap screws]: parts/Hardware.yaml#CapScrew_M4x10mm_SS -## Attach the legs to the base plate{pagestep} +## Attach the legs to the base plate {pagestep} * Get the [base plate]{make, qty:1, cat:printed} and the four [rack legs]{make, qty:4, cat:printed} that you printed earlier. -* Get an [3mm Allen key](parts/metric_allen_keys.md){qty:1, cat:tool} ready +* Get a [3mm Allen key](parts/metric_allen_keys.md){qty:1, cat:tool} ready * Use four [M4x10mm countersunk screws]{qty:4} to attach a leg to each corner of the bottom. >!! **TODO** diff --git a/documentation/index.md b/documentation/index.md index 8da84b9..b42f0da 100644 --- a/documentation/index.md +++ b/documentation/index.md @@ -8,7 +8,7 @@ Nimble is an open source, rapidly deployable, wireless mesh network. ![](../assets/img/2-23.jpg) -Anyone connected to the nimble can video and voice chat, stream videos, share files, build and run eLearning courses and website, create collaborative spreadsheets and documents, read e-books, play games, and so much more… completely offline. +Anyone connected to the nimble can video and voice chat, stream videos, share files, build and run eLearning courses and websites, create collaborative spreadsheets and documents, read e-books, play games, and so much more… completely offline. If a single internet connection is available, it can be plugged into the nimble to provide free or paid internet access to anyone on the network. The offline services and content are always available to users, regardless of internet availability. @@ -22,7 +22,7 @@ Nimble, as an open source project, is designed so that you can tailor it to your ![](../assets/img/Model_M/1.jpg) -We are [working on building a an interface for customising your nimble](https://github.com/Wakoma/nimble/pull/23). In the mean time this is an example of the assembly instructions for a specific configuration. +We are [working on building an interface for customising your nimble](https://github.com/Wakoma/nimble/pull/23). In the mean time this is an example of the assembly instructions for a specific configuration. To customise your Nimble you can go to [our GitHub](https://github.com/Wakoma/nimble). If you aren't sure where to start, you can always ask for help by [opening an issue](https://github.com/Wakoma/nimble/issues) or [starting a discussion](https://github.com/Wakoma/nimble/discussions). diff --git a/documentation/poe-explanation.md b/documentation/poe-explanation.md index 0402486..6145e91 100644 --- a/documentation/poe-explanation.md +++ b/documentation/poe-explanation.md @@ -2,7 +2,7 @@ Tags: info --- -# Power over Ethernet +# Power over Ethernet (PoE) Many of the devices in your Nimble are powered directly through the Ethernet cable. diff --git a/documentation/printing.md b/documentation/printing.md index 4077f27..4560f63 100644 --- a/documentation/printing.md +++ b/documentation/printing.md @@ -7,7 +7,7 @@ ## Print the custom components {pagestep} -Using the slicer that comes with your [3d printer](parts/3dprinter.md){qty:1, cat: tool}, slice thent the following parts, and then print them. +Using the slicer that comes with your [3d printer](parts/3dprinter.md){qty:1, cat: tool}, slice the following parts, and then print them. Some parts require support. A brim is advised for all parts. diff --git a/documentation/setup.md b/documentation/setup.md index a3483f6..586296c 100644 --- a/documentation/setup.md +++ b/documentation/setup.md @@ -1,4 +1,4 @@ -# Set Up your Nimble +# Set up your Nimble >!! **TODO** >!! @@ -8,9 +8,9 @@ {{BOM}} -## Mount the rack and access points{pagestep} +## Mount the rack and access points {pagestep} -* Take your wired Nimble rack and insert into your Peli Case. +* Take your wired Nimble rack and insert it into your Peli Case. >!! **TODO** diff --git a/documentation/wiring.md b/documentation/wiring.md index a39f774..3682822 100644 --- a/documentation/wiring.md +++ b/documentation/wiring.md @@ -8,7 +8,7 @@ Make: weight-qty: 60g --- -# Wiring The Nimble +# Wiring the Nimble >!! **TODO** >!! diff --git a/nimble_orchestration/components.py b/nimble_orchestration/components.py index 13b5e09..31d878f 100644 --- a/nimble_orchestration/components.py +++ b/nimble_orchestration/components.py @@ -172,7 +172,7 @@ def color(self): class Shelf: """ - A class for all the orchestraion information relating to a shelf + A class for all the orchestration information relating to a shelf """ def __init__(self, assembled_shelf: AssembledComponent, @@ -199,7 +199,7 @@ def device(self): @property def md(self): """ - Return the gitbuilding markdown for assembling this shelf + Return the GitBuilding markdown for assembling this shelf """ return f"# {self._device.name}\n\n This is a shelf for a {self._device.name}" diff --git a/nimble_orchestration/configuration.py b/nimble_orchestration/configuration.py index 9e24fe2..92b9d1a 100644 --- a/nimble_orchestration/configuration.py +++ b/nimble_orchestration/configuration.py @@ -87,7 +87,7 @@ def shelves(self): """ Return a list of the shelves assembled in this nimble rack. - Each object in the list is and instance of Shelf object, this holds both the information on + Each object in the list is an instance of the Shelf object, this holds both the information on the assembled shelf, and on the Device the shelf is for. """ return deepcopy(self._shelves) diff --git a/nimble_orchestration/device.py b/nimble_orchestration/device.py index bb2bec9..b77fc2b 100644 --- a/nimble_orchestration/device.py +++ b/nimble_orchestration/device.py @@ -62,7 +62,7 @@ def shelf_key(self): @property def shelf_builder_id(self): """ - shelf_builder and devices.json don't key use the same ids. devices.json seems + shelf_builder and devices.json don't use the same ids. devices.json seems to use similar terms but appends -6 as the shelf is 6 inch, and optionally -s and -t for tall and short versions. These should be unified later From 339eca036f3853c9b256d88a862e271821533c74 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Tue, 21 May 2024 08:44:27 +0100 Subject: [PATCH 7/7] Final tweaks to fix issues identified in review --- documentation/construction.md | 2 +- nimble_orchestration/components.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/construction.md b/documentation/construction.md index 1d6b251..28737bb 100644 --- a/documentation/construction.md +++ b/documentation/construction.md @@ -26,7 +26,7 @@ Make: weight-qty: 50g --- -# Construct the and populate the rack +# Construct and populate the rack {{BOM}} diff --git a/nimble_orchestration/components.py b/nimble_orchestration/components.py index 31d878f..f86b783 100644 --- a/nimble_orchestration/components.py +++ b/nimble_orchestration/components.py @@ -199,7 +199,7 @@ def device(self): @property def md(self): """ - Return the GitBuilding markdown for assembling this shelf + Return the markdown (BuildUp) for the GitBuilding page for assembling this shelf """ return f"# {self._device.name}\n\n This is a shelf for a {self._device.name}"