Merge branch 'master' of https://github.com/garthvh/Meshtastic
|
@ -10,10 +10,20 @@ If you’d like to do ‘real’ releases with your changes, the procedure is:
|
||||||
|
|
||||||
## Device
|
## Device
|
||||||
|
|
||||||
|
* Update protobufs
|
||||||
|
* * cd proto
|
||||||
|
* * git checkout master && git pull
|
||||||
|
* * cd ..
|
||||||
|
* * git add proto
|
||||||
|
* * git commit -m "updating proto submodule to latest"
|
||||||
|
* run bin/regen-protos.sh
|
||||||
* edit version.properties and check it into the root project
|
* edit version.properties and check it into the root project
|
||||||
* run bin/promote-release.sh - this should cause github to start a release build (see the CI actions)
|
* run bin/promote-release.sh - this should cause github to start a release build (see the CI actions)
|
||||||
* edit the draft release text and click publish
|
* edit the draft release text and click publish
|
||||||
|
|
||||||
|
### Update Protobufs
|
||||||
|
|
||||||
|
|
||||||
## Android
|
## Android
|
||||||
|
|
||||||
TBD
|
TBD
|
||||||
|
@ -24,10 +34,32 @@ TBD
|
||||||
|
|
||||||
## Python
|
## Python
|
||||||
|
|
||||||
if any dev wants to take this on, send me a note and I’ll bless you with pypi
|
### Pre-requistes
|
||||||
|
|
||||||
|
* Python Packages
|
||||||
|
* * pip3 install pdoc3
|
||||||
|
* * pip3 install pygatt
|
||||||
|
* * pip3 install pandoc
|
||||||
|
* * pip install twine
|
||||||
|
* https://pandoc.org/installing.html
|
||||||
|
* nanopb 0.4.4 installed
|
||||||
|
|
||||||
|
### Instructions
|
||||||
|
|
||||||
|
* Update protobufs
|
||||||
|
* * cd proto
|
||||||
|
* * git checkout master && git pull
|
||||||
|
* * cd ..
|
||||||
|
* * git add proto
|
||||||
|
* * git commit -m "updating proto submodule to latest"
|
||||||
|
* run bin/regen-protos.sh
|
||||||
* bump the version in setup.py
|
* bump the version in setup.py
|
||||||
|
* run bin/test-release.sh
|
||||||
|
* * Ensure no errors.
|
||||||
* run bin/upload-release.sh
|
* run bin/upload-release.sh
|
||||||
|
|
||||||
|
I usually just edit setup.py to bump the version number, then run "bin/upload-release.sh" (though you should use bin/test-release.sh for the first time - which is just a dry deploy to the pypi test server). This script does the build (including new docs - which will end up in the git checkin) and upload to pypi. Then I do a git commit/push and tag wit the version number.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
You need permissions in the github project to make a build:::
|
You need permissions in the github project to make a build
|
||||||
|
:::
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
id: faq
|
id: faq
|
||||||
title: Frequenty Asked Questions (FAQ)
|
title: Frequently Asked Questions (FAQ)
|
||||||
sidebar_label: Frequenty Asked Questions
|
sidebar_label: Frequently Asked Questions
|
||||||
slug: /getting-started/faq
|
slug: /getting-started/faq
|
||||||
---
|
---
|
||||||
import Tabs from '@theme/Tabs';
|
import Tabs from '@theme/Tabs';
|
||||||
|
@ -23,13 +23,13 @@ import TabItem from '@theme/TabItem';
|
||||||
## General
|
## General
|
||||||
|
|
||||||
Q: What is Meshtastic?
|
Q: What is Meshtastic?
|
||||||
* Meshtastic is most awesome long range, low power communications service on the planet earth! That's not even an exageration!
|
* Meshtastic is most awesome long range, low power communications service on the planet earth! That's not even an exaggeration!
|
||||||
|
|
||||||
Q: Where can I get additional help, ask questions or bond with the Meshtastic community?
|
Q: Where can I get additional help, ask questions or bond with the Meshtastic community?
|
||||||
* After reading this FAQ and checking out the links on the left, there are two places ... The preferred place is to check out the [Fourm](https://meshtastic.discourse.group). There you can be part of our growing community and search for previosly posts that may be similar to what you're looking for. We also have the [Meshtastic Discord](https://discord.com/invite/UQJ5QuM7vq) server where you may connect with like minded people.
|
* After reading this FAQ and checking out the links on the left, there are two places... The preferred place is to check out the [Forum](https://meshtastic.discourse.group). There you can be part of our growing community and search for previous posts that may be similar to what you're looking for. We also have the [Meshtastic Discord](https://discord.com/invite/UQJ5QuM7vq) server where you may connect with like-minded people.
|
||||||
|
|
||||||
Q: How can I contribute to Meshtastic?
|
Q: How can I contribute to Meshtastic?
|
||||||
* Everyone contributes in a different way. Join the [Fourm](https://meshtastic.discourse.group) and/or the [Meshtastic Discord](https://discord.com/invite/UQJ5QuM7vq) and introduce yourself. We're all very friendly. If you'd like to pitch in some code, check out the [Developers](https://meshtastic.org/docs/developers) menu on the left.
|
* Everyone contributes in a different way. Join the [Forum](https://meshtastic.discourse.group) and/or the [Meshtastic Discord](https://discord.com/invite/UQJ5QuM7vq) and introduce yourself. We're all very friendly. If you'd like to pitch in some code, check out the [Developers](https://meshtastic.org/docs/developers) menu on the left.
|
||||||
|
|
||||||
## Device (aka Node)
|
## Device (aka Node)
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Q: How can I tell the device not to sleep?
|
||||||
### Plugins
|
### Plugins
|
||||||
|
|
||||||
Q: What are Plugins?
|
Q: What are Plugins?
|
||||||
* Plugins are features that expand the basic device functionalty and/or integrations with other services.
|
* Plugins are features that expand the basic device functionality and/or integrate with other services.
|
||||||
|
|
||||||
Q: What plugins do we have available?
|
Q: What plugins do we have available?
|
||||||
* To see the list of available plugins, please go to: https://meshtastic.org/docs/software/plugins/plugins
|
* To see the list of available plugins, please go to: https://meshtastic.org/docs/software/plugins/plugins
|
||||||
|
@ -132,11 +132,10 @@ Q: What is a Primary Channel?
|
||||||
Q: What is a Secondary Channel?
|
Q: What is a Secondary Channel?
|
||||||
* As this is a new feature, secondary Channels work on the device and the Python Script. Support for secondary channels by other clients are pending. For more information: https://meshtastic.org/docs/software/device/device-channels#how-to-use-secondary-channels
|
* As this is a new feature, secondary Channels work on the device and the Python Script. Support for secondary channels by other clients are pending. For more information: https://meshtastic.org/docs/software/device/device-channels#how-to-use-secondary-channels
|
||||||
|
|
||||||
## Commmand Line / Python
|
## Command Line / Python
|
||||||
|
|
||||||
Q: How do I find out more about installing (and using) Meshtastic via command line?
|
Q: How do I find out more about installing (and using) Meshtastic via command line?
|
||||||
* See https://meshtastic.org/docs/software/python/python-installation
|
* See https://meshtastic.org/docs/software/python/python-installation
|
||||||
|
|
||||||
Q: How do I find out more about using python to interact?
|
Q: How do I find out more about using python to interact?
|
||||||
* See https://meshtastic.org/docs/software/python/python-usage
|
* See https://meshtastic.org/docs/software/python/python-usage
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,59 @@ import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
## Pre-requisits
|
## Pre-requisits
|
||||||
|
|
||||||
Please ensure that you use a data USB cable, as some cables provide power only and not the data lines.
|
:::tip
|
||||||
|
Please ensure that you use a data USB-C cable, as many USB-C cables provide power only and not the data lines.
|
||||||
|
:::
|
||||||
|
|
||||||
### T-Echo
|
### T-Echo
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The usb-C to usb-A cable from LILYGO is *NOT* a "data cable", and can only be used for charging.
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
#### Windows:
|
||||||
|
|
||||||
You may need to install the [USB device drivers](http://www.wch-ic.com/search?q=ch340&t=downloads) if your device does not show up when connected.
|
You may need to install the [USB device drivers](http://www.wch-ic.com/search?q=ch340&t=downloads) if your device does not show up when connected.
|
||||||
|
|
||||||
|
#### Mac OS
|
||||||
|
|
||||||
|
Last Verified T-Echo nRF52840 on: Mac OS Monterey v12.0.1 (Intel chipset)
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
You can use the latest [Apple USB-C Charge cables](https://www.apple.com/shop/product/MLL82AM/A/usb-c-charge-cable-2-m). The cable that is provided with the iPad Pro works. Older Laptop usb-C Power cables will *NOT* work, as they are missing the data lines.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
With the latest versions of MacOS, the USB Serial driver is built-in. Do *NOT* download any USB device drivers - this will actually prevent you from connecting to your T-Echo from your Mac. If you downloaded/installed any already, please Remove them.
|
||||||
|
:::
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Removing the CH34x (CH340/CH341) USB Drivers</summary>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
If you have already downloaded/installed the MacOS WCH-IC CH340 ("CH341SER_MAC") drivers via the `CH34x_Install_V1.5.pkg`, you will have to Uninstall the kernel extension:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
1.) Unplug your T-Echo<br />
|
||||||
|
2.) Open the Terminal and run:<br />
|
||||||
|
3.) sudo -rf /Library/Extensions/usbserial.kext`<br />
|
||||||
|
4.) Reboot
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
Verify successful connections with:
|
||||||
|
|
||||||
|
* Plug in your T-Echo
|
||||||
|
* Open the Terminal
|
||||||
|
* `ls -l /dev/tty.usbmodem*`
|
||||||
|
|
||||||
|
If the device file exists, you will also notice a "TECHOBOOT" volume in the Finder, or in the Terminal after double-clicking the Reset Button (see below)
|
||||||
|
|
||||||
|
* `ls /Volumes/TECHOBOOT`
|
||||||
|
|
||||||
### WisBlock RAK4631
|
### WisBlock RAK4631
|
||||||
|
|
||||||
Please ensure that you have updated the bootloader to the latest version using the information on the [RAK Documentation Center](https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Quickstart/#how-to-check-if-you-have-the-updated-rak4631-bootloader) website.
|
Please ensure that you have updated the bootloader to the latest version using the information on the [RAK Documentation Center](https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Quickstart/#how-to-check-if-you-have-the-updated-rak4631-bootloader) website.
|
||||||
|
@ -32,7 +79,15 @@ Be careful to install the correct load for your board. While it is unlikely that
|
||||||
|
|
||||||
|
|
||||||
* Connect your device to your computer with a USB cable. If you computer complains about needing to format a new drive, cancel the format command.
|
* Connect your device to your computer with a USB cable. If you computer complains about needing to format a new drive, cancel the format command.
|
||||||
* Double click the reset button on your device, this will put it into boot loader mode.
|
* Double click the `Reset` button on your device, this will put it into boot loader mode.
|
||||||
|
|
||||||
|
[<img alt="LILYGO T-Echo" src="/img/hardware/t-echo-lilygo.jpg" style={{zoom:'25%'}} />](/img/hardware/t-echo-lilygo.jpg)
|
||||||
|
|
||||||
* A new drive will then be mounted on your computer. Open this drive and you should see three files: `CURRENT.UF2`, `INDEX.HTM`, and `INFO_UF2.TXT`
|
* A new drive will then be mounted on your computer. Open this drive and you should see three files: `CURRENT.UF2`, `INDEX.HTM`, and `INFO_UF2.TXT`
|
||||||
* Copy the appropriate `firmware-xxxxx-1.2.x.uf2` file from the firmware zip file onto the new drive.
|
* Copy the appropriate `firmware-xxxxx-1.2.x.uf2` file from the firmware zip file onto the new drive.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
You are going to copy/drop "as is" 'firmware-xxxxx-1.2.x.uf2' (*NOT* over the "CURRENT.UF2" file) in the volume, and the device reboot will copy it/load it correctly.
|
||||||
|
:::
|
||||||
|
|
||||||
* Once the file has finished copying over, the device will reboot, loading the new firmware as it does.
|
* Once the file has finished copying over, the device will reboot, loading the new firmware as it does.
|
||||||
|
|
|
@ -14,10 +14,10 @@ Power settings on a Meshtastic device can be set like other user-define settings
|
||||||
For example, if we wanted to disable sleep mode, like when we put the device into router mode, we could use the command:
|
For example, if we wanted to disable sleep mode, like when we put the device into router mode, we could use the command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
meshtastic --set mesh_sds_timeout_secs MAXUNIT
|
meshtastic --set mesh_sds_timeout_secs 4294967295
|
||||||
```
|
```
|
||||||
:::note
|
:::note
|
||||||
See MAXUNIT from `mesh_sds_timeout_secs` below:
|
See MAXUINT from `mesh_sds_timeout_secs` below:
|
||||||
|
|
||||||
For a description and more information on what exactly all of these mean, please refer to [Power Management State Machine](../other/power)
|
For a description and more information on what exactly all of these mean, please refer to [Power Management State Machine](../other/power)
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ For a description and more information on what exactly all of these mean, please
|
||||||
| ls_secs | `integer` (seconds) | `0` (see note) |
|
| ls_secs | `integer` (seconds) | `0` (see note) |
|
||||||
| mesh_sds_timeout_secs | `integer` (seconds) | `0` |
|
| mesh_sds_timeout_secs | `integer` (seconds) | `0` |
|
||||||
| min_wake_secs | `integer` (seconds) | `0` |
|
| min_wake_secs | `integer` (seconds) | `0` |
|
||||||
| phone_sds_timeout_sec | `integer` (seconds) | `0` | Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, MAXUINT for disabled |
|
| phone_sds_timeout_sec | `integer` (seconds) | `0` | Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, use the value of MAXUINT or 4294967295 to disable |
|
||||||
| phone_timeout_secs | `integer` (seconds) | `0` |
|
| phone_timeout_secs | `integer` (seconds) | `0` |
|
||||||
| screen_on_secs | `integer` (seconds) | `0` |
|
| screen_on_secs | `integer` (seconds) | `0` |
|
||||||
| sds_secs | `integer` (seconds) | `0` |
|
| sds_secs | `integer` (seconds) | `0` |
|
||||||
|
@ -69,7 +69,7 @@ Power management state machine option. See the [power page](../other/power) for
|
||||||
|
|
||||||
### mesh_sds_timeout_secs
|
### mesh_sds_timeout_secs
|
||||||
|
|
||||||
Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, MAXUINT for disabled
|
Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, use the MAXUINT or 4294967295 to disable
|
||||||
|
|
||||||
### min_wake_secs
|
### min_wake_secs
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ Power management state machine option. See the [power page](../other/power)for d
|
||||||
|
|
||||||
### phone_sds_timeout_sec
|
### phone_sds_timeout_sec
|
||||||
|
|
||||||
Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, MAXUINT for disabled
|
Power management state machine option. See the [power page](../other/power) for details. 0 for default of two hours, use the MAXUINT or 4294967295 to disable
|
||||||
|
|
||||||
### phone_timeout_secs
|
### phone_timeout_secs
|
||||||
|
|
||||||
|
@ -112,7 +112,9 @@ Power management state machine option. See the [power page](../other/power) for
|
||||||
]}>
|
]}>
|
||||||
<TabItem value="cli">
|
<TabItem value="cli">
|
||||||
|
|
||||||
TODO
|
```bash
|
||||||
|
meshtastic --set mesh_sds_timeout_secs 0
|
||||||
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="android">
|
<TabItem value="android">
|
||||||
|
|
|
@ -25,6 +25,7 @@ const config = {
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
title: "Meshtastic",
|
title: "Meshtastic",
|
||||||
|
hideOnScroll: true,
|
||||||
logo: {
|
logo: {
|
||||||
alt: "Meshtastic Logo",
|
alt: "Meshtastic Logo",
|
||||||
src: "img/meshtastic-design/logo/svg/Mesh_Logo_Black.svg",
|
src: "img/meshtastic-design/logo/svg/Mesh_Logo_Black.svg",
|
||||||
|
@ -32,28 +33,14 @@ const config = {
|
||||||
},
|
},
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
|
label: "Showcase",
|
||||||
|
to: "showcase",
|
||||||
|
activeBasePath: "showcase",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Docs",
|
||||||
to: "docs/getting-started",
|
to: "docs/getting-started",
|
||||||
activeBasePath: "docs/getting-started",
|
activeBasePath: "docs/getting-started",
|
||||||
label: "Getting Started",
|
|
||||||
position: "left",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: "docs/software",
|
|
||||||
activeBasePath: "docs/software",
|
|
||||||
label: "Software",
|
|
||||||
position: "left",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: "docs/hardware",
|
|
||||||
activeBasePath: "docs/hardware",
|
|
||||||
label: "Hardware",
|
|
||||||
position: "left",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: "docs/developers",
|
|
||||||
activeBasePath: "docs/developers",
|
|
||||||
label: "Developers",
|
|
||||||
position: "left",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "https://meshtastic.discourse.group",
|
href: "https://meshtastic.discourse.group",
|
||||||
|
@ -75,20 +62,12 @@ const config = {
|
||||||
title: "Docs",
|
title: "Docs",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: "Getting Started",
|
label: "Get Started",
|
||||||
to: "docs/getting-started",
|
to: "docs/getting-started",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Software",
|
label: "Showcase",
|
||||||
to: "docs/software",
|
to: "showcase",
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Hardware",
|
|
||||||
to: "docs/hardware",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Developers",
|
|
||||||
to: "docs/developers",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -128,6 +107,7 @@ const config = {
|
||||||
searchParameters: {},
|
searchParameters: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
"@docusaurus/preset-classic",
|
"@docusaurus/preset-classic",
|
||||||
|
@ -144,6 +124,7 @@ const config = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
plugins: ["@docusaurus/plugin-ideal-image"],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"name": "meshtastic",
|
"name": "meshtastic",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docusaurus": "docusaurus",
|
"docusaurus": "docusaurus",
|
||||||
"start": "docusaurus start",
|
"start": "docusaurus start",
|
||||||
|
@ -10,9 +11,10 @@
|
||||||
"clear": "docusaurus clear"
|
"clear": "docusaurus clear"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-search": "^4.10.3",
|
"@algolia/client-search": "^4.11.0",
|
||||||
"@docusaurus/core": "^2.0.0-beta.8",
|
"@docusaurus/core": "^2.0.0-beta.9",
|
||||||
"@docusaurus/preset-classic": "^2.0.0-beta.8",
|
"@docusaurus/plugin-ideal-image": "^2.0.0-beta.9",
|
||||||
|
"@docusaurus/preset-classic": "^2.0.0-beta.9",
|
||||||
"@mdx-js/react": "^1.6.22",
|
"@mdx-js/react": "^1.6.22",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
@ -31,9 +33,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "^2.0.0-beta.8",
|
"@docusaurus/module-type-aliases": "^2.0.0-beta.9",
|
||||||
"@tsconfig/docusaurus": "^1.0.4",
|
"@tsconfig/docusaurus": "^1.0.4",
|
||||||
"@types/node": "^16.11.7",
|
"@types/node": "^16.11.10",
|
||||||
"typescript": "^4.4.4"
|
"typescript": "^4.5.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
/* stylelint-disable docusaurus/copyright-header */
|
|
||||||
/**
|
|
||||||
* Any CSS included here will be global. The classic template
|
|
||||||
* bundles Infima by default. Infima is a CSS framework designed to
|
|
||||||
* work well for content-centric websites.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* You can override the default Infima variables here. */
|
/* You can override the default Infima variables here. */
|
||||||
:root {
|
:root {
|
||||||
--ifm-color-primary: #67ea94;
|
--ifm-color-primary: #67ea94;
|
||||||
|
|
365
website/src/data/hardware/rakWireless.ts
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
export const rakWireless = {
|
||||||
|
/**
|
||||||
|
* Base modules
|
||||||
|
*/
|
||||||
|
RAK19003: {
|
||||||
|
name: "RAK19003",
|
||||||
|
details: "WisBlock Mini Base Board",
|
||||||
|
image: "/img/hardware/rak/RAK19003.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19003/Overview/",
|
||||||
|
},
|
||||||
|
RAK5005_O: {
|
||||||
|
name: "RAK5005-O",
|
||||||
|
details: "WisBlock Base Board",
|
||||||
|
image: "/img/hardware/rak/RAK5005-O.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5005-O/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core modules
|
||||||
|
*/
|
||||||
|
RAK11200: {
|
||||||
|
name: "RAK11200",
|
||||||
|
details: "WisBlock WiFi Module",
|
||||||
|
image: "/img/hardware/rak/RAK11200.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11200/Overview/",
|
||||||
|
},
|
||||||
|
RAK11310: {
|
||||||
|
name: "RAK11310",
|
||||||
|
details: "WisBlock LPWAN Module",
|
||||||
|
image: "/img/hardware/rak/RAK11310.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11310/Overview/",
|
||||||
|
},
|
||||||
|
RAK4631: {
|
||||||
|
name: "RAK4631",
|
||||||
|
details: "WisBlock LPWAN Module",
|
||||||
|
image: "/img/hardware/rak/RAK4631.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wireless modules
|
||||||
|
*/
|
||||||
|
RAK13101: {
|
||||||
|
name: "RAK13101",
|
||||||
|
details: "WisBlock GSM/GPRS Module",
|
||||||
|
image: "/img/hardware/rak/RAK13101.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13101/Overview/",
|
||||||
|
},
|
||||||
|
RAK2305: {
|
||||||
|
name: "RAK2305",
|
||||||
|
details: "WisBlock WiFi Interface Module",
|
||||||
|
image: "/img/hardware/rak/RAK2305.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK2305/Overview/",
|
||||||
|
},
|
||||||
|
RAK5860: {
|
||||||
|
name: "RAK5860",
|
||||||
|
details: "WisBlock NB-IoT Interface Module",
|
||||||
|
image: "/img/hardware/rak/RAK5860.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5860/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sensor modules
|
||||||
|
*/
|
||||||
|
RAK12003: {
|
||||||
|
name: "RAK12003",
|
||||||
|
details: "WisBlock Infrared Temperature Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK12003.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12003/Overview/",
|
||||||
|
},
|
||||||
|
RAK12004: {
|
||||||
|
name: "RAK12004",
|
||||||
|
details: "WisBlock MQ2 Gas Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK12004.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12004/Overview/",
|
||||||
|
},
|
||||||
|
RAK12005: {
|
||||||
|
name: "RAK12005",
|
||||||
|
details: "WisBlock Rain Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK12005.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12005/Overview/",
|
||||||
|
},
|
||||||
|
RAK12006: {
|
||||||
|
name: "RAK12006",
|
||||||
|
details: "WisBlock PIR Module",
|
||||||
|
image: "/img/hardware/rak/RAK12006.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12006/Overview/",
|
||||||
|
},
|
||||||
|
RAK12007: {
|
||||||
|
name: "RAK12007",
|
||||||
|
details: "WisBlock Ultrasonic Module",
|
||||||
|
image: "/img/hardware/rak/RAK12007.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12007/Overview/",
|
||||||
|
},
|
||||||
|
RAK12009: {
|
||||||
|
name: "RAK12009",
|
||||||
|
details: "WisBlock MQ3 Alcohol Gas Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK12009.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12009/Overview/",
|
||||||
|
},
|
||||||
|
RAK12010: {
|
||||||
|
name: "RAK12010",
|
||||||
|
details: "WisBlock Ambient Light Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK12010.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12010/Overview/",
|
||||||
|
},
|
||||||
|
RAK12011: {
|
||||||
|
name: "RAK12011",
|
||||||
|
details: "WisBlock Barometer WT Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK12011.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12011/Overview/",
|
||||||
|
},
|
||||||
|
RAK12012: {
|
||||||
|
name: "RAK12012",
|
||||||
|
details: "WisBlock Heart Rate Module",
|
||||||
|
image: "/img/hardware/rak/RAK12012.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12012/Overview/",
|
||||||
|
},
|
||||||
|
RAK12015: {
|
||||||
|
name: "RAK12015",
|
||||||
|
details: "WisBlock Vibration Detection Module",
|
||||||
|
image: "/img/hardware/rak/RAK12015.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12015/Overview/",
|
||||||
|
},
|
||||||
|
RAK12500: {
|
||||||
|
name: "RAK12500",
|
||||||
|
details: "WisBlock GNSS Location Module",
|
||||||
|
image: "/img/hardware/rak/RAK12500.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12500/Overview/",
|
||||||
|
},
|
||||||
|
RAK16000: {
|
||||||
|
name: "RAK16000",
|
||||||
|
details: "WisBlock DC Current Module",
|
||||||
|
image: "/img/hardware/rak/RAK16000.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK16000/Overview/",
|
||||||
|
},
|
||||||
|
RAK18000: {
|
||||||
|
name: "RAK18000",
|
||||||
|
details: "WisBlock PDM Stereo Microphone Module",
|
||||||
|
image: "/img/hardware/rak/RAK18000.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK18000/Overview/",
|
||||||
|
},
|
||||||
|
RAK1901: {
|
||||||
|
name: "RAK1901",
|
||||||
|
details: "WisBlock Temperature and Humidity Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK1901.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1901/Overview/",
|
||||||
|
},
|
||||||
|
RAK1902: {
|
||||||
|
name: "RAK1902",
|
||||||
|
details: "WisBlock Barometer Pressure Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK1902.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1902/Overview/",
|
||||||
|
},
|
||||||
|
RAK1903: {
|
||||||
|
name: "RAK1903",
|
||||||
|
details: "WisBlock Ambient Light Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK1903.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1903/Overview/",
|
||||||
|
},
|
||||||
|
RAK1904: {
|
||||||
|
name: "RAK1904",
|
||||||
|
details: "WisBlock 3-axis Acceleration Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK1904.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1904/Overview/",
|
||||||
|
},
|
||||||
|
RAK1906: {
|
||||||
|
name: "RAK1906",
|
||||||
|
details: "WisBlock Environmental Sensor",
|
||||||
|
image: "/img/hardware/rak/RAK1906.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1906/Overview/",
|
||||||
|
},
|
||||||
|
RAK1910: {
|
||||||
|
name: "RAK1910",
|
||||||
|
details: "WisBlock GNSS Location Module",
|
||||||
|
image: "/img/hardware/rak/RAK1910.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1910/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface modules
|
||||||
|
*/
|
||||||
|
RAK13001: {
|
||||||
|
name: "RAK13001",
|
||||||
|
details: "WisBlock Relay IO Module",
|
||||||
|
image: "/img/hardware/rak/RAK13001.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13001/Overview/",
|
||||||
|
},
|
||||||
|
RAK13002: {
|
||||||
|
name: "RAK13002",
|
||||||
|
details: "WisBlock IO Module",
|
||||||
|
image: "/img/hardware/rak/RAK13002.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13002/Overview/",
|
||||||
|
},
|
||||||
|
RAK13003: {
|
||||||
|
name: "RAK13003",
|
||||||
|
details: "WisBlock IO Expansion Module",
|
||||||
|
image: "/img/hardware/rak/RAK13003.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13003/Overview/",
|
||||||
|
},
|
||||||
|
RAK13004: {
|
||||||
|
name: "RAK13004",
|
||||||
|
details: "WisBlock PWM Expander Module",
|
||||||
|
image: "/img/hardware/rak/RAK13004.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13004/Overview/",
|
||||||
|
},
|
||||||
|
RAK13005: {
|
||||||
|
name: "RAK13005",
|
||||||
|
details: "WisBlock LIN Module",
|
||||||
|
image: "/img/hardware/rak/RAK13005.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13005/Overview/",
|
||||||
|
},
|
||||||
|
RAK14002: {
|
||||||
|
name: "RAK14002",
|
||||||
|
details: "WisBlock Touch Sensor Module",
|
||||||
|
image: "/img/hardware/rak/RAK14002.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK14002/Overview/",
|
||||||
|
},
|
||||||
|
RAK16001: {
|
||||||
|
name: "RAK16001",
|
||||||
|
details: "WisBlock ADC Module",
|
||||||
|
image: "/img/hardware/rak/RAK16001.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK16001/Overview/",
|
||||||
|
},
|
||||||
|
RAK1920: {
|
||||||
|
name: "RAK1920",
|
||||||
|
details: "WisBlock Sensor Adapter Module",
|
||||||
|
image: "/img/hardware/rak/RAK1920.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1920/Overview/",
|
||||||
|
},
|
||||||
|
RAK5801: {
|
||||||
|
name: "RAK5801",
|
||||||
|
details: "WisBlock 4-20mA Interface Module",
|
||||||
|
image: "/img/hardware/rak/RAK5801.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5801/Overview/",
|
||||||
|
},
|
||||||
|
RAK5802: {
|
||||||
|
name: "RAK5802",
|
||||||
|
details: "WisBlock RS485 Interface Module",
|
||||||
|
image: "/img/hardware/rak/RAK5802.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5802/Overview/",
|
||||||
|
},
|
||||||
|
RAK5804: {
|
||||||
|
name: "RAK5804",
|
||||||
|
details: "WisBlock Interface Extension Module",
|
||||||
|
image: "/img/hardware/rak/RAK5804.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5804/Overview/",
|
||||||
|
},
|
||||||
|
RAK5811: {
|
||||||
|
name: "RAK5811",
|
||||||
|
details: "WisBlock 0-5V Interface Module",
|
||||||
|
image: "/img/hardware/rak/RAK5811.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK5811/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display Modules
|
||||||
|
*/
|
||||||
|
RAK14000: {
|
||||||
|
name: "RAK14000",
|
||||||
|
details: "WisBlock E-Ink Display",
|
||||||
|
image: "/img/hardware/rak/RAK14000.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK14000/Overview/",
|
||||||
|
},
|
||||||
|
RAK14001: {
|
||||||
|
name: "RAK14001",
|
||||||
|
details: "WisBlock RGB LED Module",
|
||||||
|
image: "/img/hardware/rak/RAK14001.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK14001/Overview/",
|
||||||
|
},
|
||||||
|
RAK14003: {
|
||||||
|
name: "RAK14003",
|
||||||
|
details: "WisBlock LED Bar Graph Module",
|
||||||
|
image: "/img/hardware/rak/RAK14003.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK14003/Overview/",
|
||||||
|
},
|
||||||
|
RAK1921: {
|
||||||
|
name: "RAK1921",
|
||||||
|
details: "WisBlock OLED Display",
|
||||||
|
image: "/img/hardware/rak/RAK1921.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1921/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra modules
|
||||||
|
*/
|
||||||
|
RAK12002: {
|
||||||
|
name: "RAK12002",
|
||||||
|
details: "WisBlock RTC Module",
|
||||||
|
image: "/img/hardware/rak/RAK12002.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK12002/Overview/",
|
||||||
|
},
|
||||||
|
RAK18001: {
|
||||||
|
name: "RAK18001",
|
||||||
|
details: "WisBlock Buzzer Module",
|
||||||
|
image: "/img/hardware/rak/RAK18001.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK18001/Overview/",
|
||||||
|
},
|
||||||
|
RAK19005: {
|
||||||
|
name: "RAK19005",
|
||||||
|
details: "WisBlock Sensor Extension Cable",
|
||||||
|
image: "/img/hardware/rak/RAK19005.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19005/Overview/",
|
||||||
|
},
|
||||||
|
RAK19008: {
|
||||||
|
name: "RAK19008",
|
||||||
|
details: "WisBlock IO Extension Cable",
|
||||||
|
image: "/img/hardware/rak/RAK19008.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19008/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage modules
|
||||||
|
*/
|
||||||
|
RAK15000: {
|
||||||
|
name: "RAK15000",
|
||||||
|
details: "WisBlock EEPROM Module",
|
||||||
|
image: "/img/hardware/rak/RAK15000.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK15000/Overview/",
|
||||||
|
},
|
||||||
|
RAK15001: {
|
||||||
|
name: "RAK15001",
|
||||||
|
details: "WisBlock Flash Module",
|
||||||
|
image: "/img/hardware/rak/RAK15001.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK15001/Overview/",
|
||||||
|
},
|
||||||
|
RAK15002: {
|
||||||
|
name: "RAK15002",
|
||||||
|
details: "WisBlock Micro SD Card Module",
|
||||||
|
image: "/img/hardware/rak/RAK15002.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK15002/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power modules
|
||||||
|
*/
|
||||||
|
RAK19002: {
|
||||||
|
name: "RAK19002",
|
||||||
|
details: "WisBlock Boost Module",
|
||||||
|
image: "/img/hardware/rak/RAK19002.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19002/Overview/",
|
||||||
|
},
|
||||||
|
RAK19004: {
|
||||||
|
name: "RAK19004",
|
||||||
|
details: "WisBlock Green Power Module",
|
||||||
|
image: "/img/hardware/rak/RAK19004.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19004/Overview/",
|
||||||
|
},
|
||||||
|
RAK19006: {
|
||||||
|
name: "RAK19006",
|
||||||
|
details: "WisBlock Wireless Charge Module",
|
||||||
|
image: "/img/hardware/rak/RAK19006.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK19006/Overview/",
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Motor modules
|
||||||
|
*/
|
||||||
|
RAK17000: {
|
||||||
|
name: "RAK17000",
|
||||||
|
details: "WisBlock Motor Control Module",
|
||||||
|
image: "/img/hardware/rak/RAK17000.png",
|
||||||
|
url: "https://docs.rakwireless.com/Product-Categories/WisBlock/RAK17000/Overview/",
|
||||||
|
},
|
||||||
|
};
|
80
website/src/data/networks/_overview.ts
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import { ShowcaseNetwork } from '../../utils/showcase';
|
||||||
|
|
||||||
|
export const networks: ShowcaseNetwork[] = [
|
||||||
|
{
|
||||||
|
id: "ckwhq3l5a000008kufkw8f3dg",
|
||||||
|
title: "Network 1",
|
||||||
|
description:
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget dui mollis.",
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
latitude: -37.656719,
|
||||||
|
longitude: 145.632219,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: -37.633466,
|
||||||
|
longitude: 145.692371,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: -37.559148,
|
||||||
|
longitude: 145.735771,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tags: ["community", "largeNetwork"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "ckwhq4jch000108kuawlwaz0y",
|
||||||
|
title: "Network 2",
|
||||||
|
description:
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut mattis felis.",
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
latitude: -27.069626,
|
||||||
|
longitude: 139.961265,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: -26.520932,
|
||||||
|
longitude: 139.773739,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: -26.233798,
|
||||||
|
longitude: 139.752755,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tags: ["favorite", "portable"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "ckwhq4skm000208ku4h8ta03q",
|
||||||
|
title: "Network 3",
|
||||||
|
description:
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, faucibus ut.",
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
latitude: -5.64,
|
||||||
|
longitude: 134.749708,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: -5.561545,
|
||||||
|
longitude: 134.706247,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tags: ["longDistance"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "ckwhq4yau000308kufwqz6pri",
|
||||||
|
title: "Network 4",
|
||||||
|
description:
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce luctus.",
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
latitude: 46.658126,
|
||||||
|
longitude: 62.22795,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
latitude: 46.697482,
|
||||||
|
longitude: 61.560184,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tags: ["favorite", "largeNetwork", "offGrid"],
|
||||||
|
},
|
||||||
|
];
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { NetworkWriteup } from '../../../utils/showcase';
|
||||||
|
import { rakWireless } from '../../hardware/rakWireless';
|
||||||
|
|
||||||
|
export const writeup: NetworkWriteup = {
|
||||||
|
summary: "This is the article summary.",
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
heading: "This is the first heading.",
|
||||||
|
body: "This is the first body segment.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "This is the second heading.",
|
||||||
|
body: "This is the second body segment.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "This is the second heading.",
|
||||||
|
body: "This is the second body segment.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
bom: [
|
||||||
|
{
|
||||||
|
name: "This is the first material name.",
|
||||||
|
details: "This is the first material details.",
|
||||||
|
image: "https://example.com/image.png",
|
||||||
|
url: "https://example.com/material",
|
||||||
|
},
|
||||||
|
rakWireless.RAK19003,
|
||||||
|
rakWireless.RAK5005_O,
|
||||||
|
rakWireless.RAK11200,
|
||||||
|
rakWireless.RAK11310,
|
||||||
|
rakWireless.RAK4631,
|
||||||
|
rakWireless.RAK13101,
|
||||||
|
rakWireless.RAK2305,
|
||||||
|
rakWireless.RAK5860,
|
||||||
|
rakWireless.RAK12003,
|
||||||
|
rakWireless.RAK12004,
|
||||||
|
rakWireless.RAK12005,
|
||||||
|
rakWireless.RAK12006,
|
||||||
|
rakWireless.RAK12007,
|
||||||
|
rakWireless.RAK12009,
|
||||||
|
rakWireless.RAK12010,
|
||||||
|
rakWireless.RAK12011,
|
||||||
|
rakWireless.RAK12012,
|
||||||
|
rakWireless.RAK12015,
|
||||||
|
rakWireless.RAK12500,
|
||||||
|
rakWireless.RAK16000,
|
||||||
|
rakWireless.RAK18000,
|
||||||
|
rakWireless.RAK1901,
|
||||||
|
rakWireless.RAK1902,
|
||||||
|
rakWireless.RAK1903,
|
||||||
|
rakWireless.RAK1904,
|
||||||
|
rakWireless.RAK1906,
|
||||||
|
rakWireless.RAK1910,
|
||||||
|
rakWireless.RAK13001,
|
||||||
|
rakWireless.RAK13002,
|
||||||
|
rakWireless.RAK13003,
|
||||||
|
rakWireless.RAK13004,
|
||||||
|
rakWireless.RAK13005,
|
||||||
|
rakWireless.RAK14002,
|
||||||
|
rakWireless.RAK16001,
|
||||||
|
rakWireless.RAK1920,
|
||||||
|
rakWireless.RAK5801,
|
||||||
|
rakWireless.RAK5802,
|
||||||
|
rakWireless.RAK5804,
|
||||||
|
rakWireless.RAK5811,
|
||||||
|
rakWireless.RAK14000,
|
||||||
|
rakWireless.RAK14001,
|
||||||
|
rakWireless.RAK14003,
|
||||||
|
rakWireless.RAK1921,
|
||||||
|
rakWireless.RAK12002,
|
||||||
|
rakWireless.RAK18001,
|
||||||
|
rakWireless.RAK19005,
|
||||||
|
rakWireless.RAK19008,
|
||||||
|
rakWireless.RAK15000,
|
||||||
|
rakWireless.RAK15001,
|
||||||
|
rakWireless.RAK15002,
|
||||||
|
rakWireless.RAK19002,
|
||||||
|
rakWireless.RAK19004,
|
||||||
|
rakWireless.RAK19006,
|
||||||
|
rakWireless.RAK17000,
|
||||||
|
],
|
||||||
|
author: {
|
||||||
|
name: "Author Name",
|
||||||
|
about: "This is the author's about text.",
|
||||||
|
avatarUrl: "https://avatars0.githubusercontent.com/u/1234?s=460&v=4",
|
||||||
|
url: "",
|
||||||
|
},
|
||||||
|
};
|
27
website/src/hooks/useFilteredNetworks.tsx
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { ShowcaseNetwork, sortedNetworks, TagType } from '../utils/showcase';
|
||||||
|
import { useSelectedTags } from './useSelectedTags';
|
||||||
|
|
||||||
|
const filterNetworks = (
|
||||||
|
showcaseNetworks: ShowcaseNetwork[],
|
||||||
|
selectedTags: TagType[]
|
||||||
|
) => {
|
||||||
|
if (selectedTags.length === 0) {
|
||||||
|
return showcaseNetworks;
|
||||||
|
}
|
||||||
|
return showcaseNetworks.filter((showcaseNetwork) => {
|
||||||
|
if (showcaseNetwork.tags.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return selectedTags.every((tag) => showcaseNetwork.tags.includes(tag));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFilteredNetworks = () => {
|
||||||
|
const selectedTags = useSelectedTags();
|
||||||
|
return React.useMemo(
|
||||||
|
() => filterNetworks(sortedNetworks, selectedTags),
|
||||||
|
[selectedTags]
|
||||||
|
);
|
||||||
|
};
|
17
website/src/hooks/useSelectedTags.tsx
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useLocation } from '@docusaurus/router';
|
||||||
|
|
||||||
|
import { readSearchTags } from '../pages/showcase/_components/TagSelect';
|
||||||
|
import { TagType } from '../utils/showcase';
|
||||||
|
|
||||||
|
export const useSelectedTags = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
const [selectedTags, setSelectedTags] = React.useState<TagType[]>([]);
|
||||||
|
React.useEffect(() => {
|
||||||
|
const tags = readSearchTags(location.search);
|
||||||
|
setSelectedTags(tags);
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
|
return selectedTags;
|
||||||
|
};
|
|
@ -1,13 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import Head from '@docusaurus/Head';
|
||||||
|
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
import Head from '@docusaurus/Head';
|
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
|
@ -15,7 +11,10 @@ const features = [
|
||||||
imageUrl: "img/homepage/messages.svg",
|
imageUrl: "img/homepage/messages.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Off-grid messaging using inexpensive hardware to create your personal mesh. Radios forward messages to the next to flood the network. Communicate kilometers/miles between nodes. Internet-connected relay nodes enable the conversation to move online too.
|
Off-grid messaging using inexpensive hardware to create your personal
|
||||||
|
mesh. Radios forward messages to the next to flood the network.
|
||||||
|
Communicate kilometers/miles between nodes. Internet-connected relay
|
||||||
|
nodes enable the conversation to move online too.
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -24,7 +23,10 @@ const features = [
|
||||||
imageUrl: "img/homepage/encryption.svg",
|
imageUrl: "img/homepage/encryption.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Messages are AES256 encrypted. Only radios supplied with your channel settings (which includes the key) should be able to read your messages. Using multichannel settings you can send encrypted messages on one channel and still participate in a default Meshtastic mesh.
|
Messages are AES256 encrypted. Only radios supplied with your channel
|
||||||
|
settings (which includes the key) should be able to read your messages.
|
||||||
|
Using multichannel settings you can send encrypted messages on one
|
||||||
|
channel and still participate in a default Meshtastic mesh.
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -33,7 +35,9 @@ const features = [
|
||||||
imageUrl: "img/homepage/battery.svg",
|
imageUrl: "img/homepage/battery.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Go for days on end and on a single battery or extend it infinitely with a solar cell. Power management ensures the device will last the duration of your use.
|
Go for days on end and on a single battery or extend it infinitely with
|
||||||
|
a solar cell. Power management ensures the device will last the duration
|
||||||
|
of your use.
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -42,7 +46,10 @@ const features = [
|
||||||
imageUrl: "img/homepage/extendable.svg",
|
imageUrl: "img/homepage/extendable.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Create a highly scalable mesh with hardware on a multitude of platforms to fit your unique requirements: Create an environment monitoring mesh and produce real-time heatmaps, or maybe decentralised, encrypted messaging network, your imagination is the limit.
|
Create a highly scalable mesh with hardware on a multitude of platforms
|
||||||
|
to fit your unique requirements: Create an environment monitoring mesh
|
||||||
|
and produce real-time heatmaps, or maybe decentralised, encrypted
|
||||||
|
messaging network, your imagination is the limit.
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -51,7 +58,9 @@ const features = [
|
||||||
imageUrl: "img/homepage/platforms.svg",
|
imageUrl: "img/homepage/platforms.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Meshtastic clients are built or being built for all major desktop and mobile platforms. Linux, Windows, Mac, Android, and iOS are all supported or well on their way to being supported.
|
Meshtastic clients are built or being built for all major desktop and
|
||||||
|
mobile platforms. Linux, Windows, Mac, Android, and iOS are all
|
||||||
|
supported or well on their way to being supported.
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -60,7 +69,8 @@ const features = [
|
||||||
imageUrl: "img/homepage/opensource.svg",
|
imageUrl: "img/homepage/opensource.svg",
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
All Meshtastic software is open source. If you want an improvement, submit a pull request or file an issue on Github. Happy coding!
|
All Meshtastic software is open source. If you want an improvement,
|
||||||
|
submit a pull request or file an issue on Github. Happy coding!
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -69,10 +79,10 @@ const features = [
|
||||||
function Feature({ imageUrl, title, description }) {
|
function Feature({ imageUrl, title, description }) {
|
||||||
const imgUrl = useBaseUrl(imageUrl);
|
const imgUrl = useBaseUrl(imageUrl);
|
||||||
return (
|
return (
|
||||||
<div className={clsx("col col--4", styles.feature)}>
|
<div className="col col--4">
|
||||||
{imgUrl && (
|
{imgUrl && (
|
||||||
<div className="text--center">
|
<div className="text--center">
|
||||||
<img className={styles.featureImage} src={imgUrl} alt={title} />
|
<img width={200} height={200} src={imgUrl} alt={title} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
|
@ -90,7 +100,9 @@ function Home() {
|
||||||
<meta property="og:title" content="Meshtastic" />
|
<meta property="og:title" content="Meshtastic" />
|
||||||
<meta
|
<meta
|
||||||
property="og:image"
|
property="og:image"
|
||||||
content={useBaseUrl("img/meshtastic-design/web/social-preview-1200x630.png")}
|
content={useBaseUrl(
|
||||||
|
"img/meshtastic-design/web/social-preview-1200x630.png"
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<meta
|
<meta
|
||||||
property="og:description"
|
property="og:description"
|
||||||
|
@ -99,7 +111,7 @@ function Home() {
|
||||||
<meta property="og:url" content="https://meshtastic.org/" />
|
<meta property="og:url" content="https://meshtastic.org/" />
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
</Head>
|
</Head>
|
||||||
<header className={clsx("hero hero--primary", styles.heroBanner)}>
|
<header style={{ textAlign: "center" }} className="hero hero--primary">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h1 className="hero__title">
|
<h1 className="hero__title">
|
||||||
<img
|
<img
|
||||||
|
@ -114,7 +126,9 @@ function Home() {
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
{features && features.length > 0 && (
|
{features && features.length > 0 && (
|
||||||
<section className={styles.features}>
|
<section
|
||||||
|
style={{ display: "flex", alignItems: "center", padding: "2rem" }}
|
||||||
|
>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{features.map((props, idx) => (
|
{features.map((props, idx) => (
|
||||||
|
|
99
website/src/pages/showcase/_components/Card.tsx
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Image from '@theme/IdealImage';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Node,
|
||||||
|
ShowcaseNetwork,
|
||||||
|
sortBy,
|
||||||
|
Tag,
|
||||||
|
TagList,
|
||||||
|
Tags,
|
||||||
|
TagType,
|
||||||
|
} from '../../../utils/showcase';
|
||||||
|
|
||||||
|
interface Props extends Tag {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapUrl = (nodes: Node[]): string => {
|
||||||
|
const width = 900;
|
||||||
|
const height = 400;
|
||||||
|
const access_token =
|
||||||
|
"pk.eyJ1Ijoic2FjaGF3IiwiYSI6ImNrNW9meXozZjBsdW0zbHBjM2FnNnV6cmsifQ.3E4n8eFGD9ZOFo-XDVeZnQ";
|
||||||
|
const nodeCoords = nodes.map(
|
||||||
|
({ latitude, longitude }) => `pin-l+67ea94(${longitude},${latitude})`
|
||||||
|
);
|
||||||
|
|
||||||
|
return `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/static/${nodeCoords}/auto/${width}x${height}@2x?access_token=${access_token}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CardTags = ({ tags }: { tags: TagType[] }) => {
|
||||||
|
const tagObjects = tags.map((tag) => ({ tag, ...Tags[tag] }));
|
||||||
|
const tagObjectsSorted = sortBy(tagObjects, (tagObject) =>
|
||||||
|
TagList.indexOf(tagObject.tag)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className="pills">
|
||||||
|
{tagObjectsSorted.map(({ color, description, label }, index) => {
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
display: "inline-flex",
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
gap: "0.3rem",
|
||||||
|
fontSize: "0.6rem",
|
||||||
|
lineHeight: "1rem",
|
||||||
|
cursor: "default",
|
||||||
|
userSelect: "none",
|
||||||
|
padding: "0.2rem",
|
||||||
|
border: "2px solid gray",
|
||||||
|
}}
|
||||||
|
className="pills__item"
|
||||||
|
title={description}
|
||||||
|
>
|
||||||
|
<span>{label.toLowerCase()}</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
backgroundColor: color,
|
||||||
|
width: "0.5rem",
|
||||||
|
height: "0.5rem",
|
||||||
|
borderRadius: "50%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Card = React.memo(
|
||||||
|
({ showcaseNetwork }: { showcaseNetwork: ShowcaseNetwork }) => (
|
||||||
|
<div className="card">
|
||||||
|
<div className="card__image">
|
||||||
|
<Image
|
||||||
|
img={mapUrl(showcaseNetwork.nodes)}
|
||||||
|
alt={showcaseNetwork.title}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card__body">
|
||||||
|
<h4>{showcaseNetwork.title}</h4>
|
||||||
|
<small>{showcaseNetwork.description}</small>
|
||||||
|
</div>
|
||||||
|
<div className="card__footer">
|
||||||
|
<a
|
||||||
|
href={`?id=${showcaseNetwork.id}`}
|
||||||
|
className="button button--primary button--block"
|
||||||
|
style={{ marginBottom: "0.5rem" }}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</a>
|
||||||
|
<CardTags tags={showcaseNetwork.tags} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
);
|
74
website/src/pages/showcase/_components/Filters.tsx
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { FiHeart } from 'react-icons/fi';
|
||||||
|
|
||||||
|
import { TagList, Tags } from '../../../utils/showcase';
|
||||||
|
import { TagSelect } from './TagSelect';
|
||||||
|
|
||||||
|
export const Filters = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<section className="container margin-top--l margin-bottom--lg">
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
padding: "0",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{TagList.map((tag, i) => {
|
||||||
|
const { label, description, color } = Tags[tag];
|
||||||
|
const id = `showcase_checkbox_id_${tag};`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
style={{
|
||||||
|
boxSizing: "border-box",
|
||||||
|
position: "relative",
|
||||||
|
display: "inline-flex",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "2rem",
|
||||||
|
marginTop: "0.5rem",
|
||||||
|
marginRight: "0.5rem",
|
||||||
|
fontSize: "0.875rem",
|
||||||
|
lineHeight: "1.25rem",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
userSelect: "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TagSelect
|
||||||
|
tag={tag}
|
||||||
|
id={id}
|
||||||
|
label={label}
|
||||||
|
icon={
|
||||||
|
tag === "favorite" ? (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
marginLeft: "0.5rem",
|
||||||
|
color: "rgb(190 24 93)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiHeart />
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
backgroundColor: color,
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: "50%",
|
||||||
|
marginLeft: 8,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
117
website/src/pages/showcase/_components/Network.tsx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { networks } from '../../../data/networks/_overview';
|
||||||
|
import { NetworkWriteup } from '../../../utils/showcase';
|
||||||
|
|
||||||
|
interface NetworkProps {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Network = ({ id }: NetworkProps): JSX.Element => {
|
||||||
|
import(`../../../data/networks/${id}/writeup.ts`).then((data) => {
|
||||||
|
setNetworkWriteup(data.writeup as NetworkWriteup);
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log(data);
|
||||||
|
const [networkWriteup, setNetworkWriteup] = React.useState<NetworkWriteup>();
|
||||||
|
React.useEffect(() => {
|
||||||
|
// data.then((data) => setNetworkWriteup(data));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const network = networks.find((network) => network.id === id);
|
||||||
|
|
||||||
|
return network && networkWriteup ? (
|
||||||
|
<div className="container">
|
||||||
|
<h1>{network.title}</h1>
|
||||||
|
<p>{network.description}</p>
|
||||||
|
<div className="avatar">
|
||||||
|
<img
|
||||||
|
src={networkWriteup.author.avatarUrl}
|
||||||
|
alt={networkWriteup.author.name}
|
||||||
|
className="avatar__photo"
|
||||||
|
/>
|
||||||
|
<div className="avatar__intro">
|
||||||
|
<div className="avatar__name">{networkWriteup.author.name}</div>
|
||||||
|
<div className="avatar__subtitle">{networkWriteup.author.about}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{networkWriteup.body.map((segment, index) => (
|
||||||
|
<div key={index}>
|
||||||
|
<h2>{segment.heading}</h2>
|
||||||
|
<p>{segment.body}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="card"
|
||||||
|
style={{
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
maxWidth: "900px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="card__header"
|
||||||
|
style={{
|
||||||
|
margin: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h2>Bill of Materials</h2>
|
||||||
|
</div>
|
||||||
|
<div className="card__body">
|
||||||
|
{networkWriteup.bom.map((material, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
borderTop: "2px solid gray",
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "4rem",
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={material.image}
|
||||||
|
height="auto"
|
||||||
|
width="100%"
|
||||||
|
style={{
|
||||||
|
margin: "auto",
|
||||||
|
padding: "4px",
|
||||||
|
display: "block",
|
||||||
|
maxWidth: "60px",
|
||||||
|
maxHeight: "60px",
|
||||||
|
width: "auto",
|
||||||
|
height: "auto",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="avatar__intro">
|
||||||
|
<div className="avatar__name">{material.name}</div>
|
||||||
|
<small className="avatar__subtitle">{material.details}</small>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href={material.url}
|
||||||
|
className="button button--outline button--secondary"
|
||||||
|
style={{
|
||||||
|
marginTop: "auto",
|
||||||
|
marginBottom: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<h1>Network not found</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
97
website/src/pages/showcase/_components/Networks.tsx
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { FiHeart, FiSearch } from 'react-icons/fi';
|
||||||
|
|
||||||
|
import { useFilteredNetworks } from '../../../hooks/useFilteredNetworks';
|
||||||
|
import { useSelectedTags } from '../../../hooks/useSelectedTags';
|
||||||
|
import { ShowcaseNetwork, sortedNetworks } from '../../../utils/showcase';
|
||||||
|
import { Card } from './Card';
|
||||||
|
|
||||||
|
const favoriteNetworks = sortedNetworks.filter((network) =>
|
||||||
|
network.tags.includes("favorite")
|
||||||
|
);
|
||||||
|
const otherNetworks = sortedNetworks.filter(
|
||||||
|
(network) => !network.tags.includes("favorite")
|
||||||
|
);
|
||||||
|
|
||||||
|
interface NetworkSectionProps {
|
||||||
|
title: string;
|
||||||
|
icon?: JSX.Element;
|
||||||
|
iconColor?: string;
|
||||||
|
networks: ShowcaseNetwork[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetworkSection = ({
|
||||||
|
title,
|
||||||
|
icon,
|
||||||
|
iconColor,
|
||||||
|
networks,
|
||||||
|
}: NetworkSectionProps): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="container margin-top--lg">
|
||||||
|
<div
|
||||||
|
className="margin-bottom--sm"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
{icon && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
marginBottom: "0.5rem",
|
||||||
|
marginLeft: "0.5rem",
|
||||||
|
fontSize: "1.25rem",
|
||||||
|
lineHeight: "1.75rem",
|
||||||
|
color: iconColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
display: "grid",
|
||||||
|
gap: "1.5rem",
|
||||||
|
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
|
||||||
|
paddingLeft: "0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{networks.map((network) => (
|
||||||
|
<Card key={network.title} showcaseNetwork={network} />
|
||||||
|
))}
|
||||||
|
{networks.length === 0 && <h2>No result</h2>}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Networks = (): JSX.Element => {
|
||||||
|
const selectedTags = useSelectedTags();
|
||||||
|
const filteredNetworks = useFilteredNetworks();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="margin-top--lg margin-bottom--xl">
|
||||||
|
{selectedTags.length === 0 ? (
|
||||||
|
<>
|
||||||
|
<NetworkSection
|
||||||
|
title="Our favorites"
|
||||||
|
icon={<FiHeart />}
|
||||||
|
iconColor="rgb(190 24 93)"
|
||||||
|
networks={favoriteNetworks}
|
||||||
|
/>
|
||||||
|
<NetworkSection title="All networks" networks={otherNetworks} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<NetworkSection
|
||||||
|
title="Results"
|
||||||
|
icon={<FiSearch />}
|
||||||
|
networks={filteredNetworks}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
57
website/src/pages/showcase/_components/TagSelect.tsx
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useHistory, useLocation } from '@docusaurus/router';
|
||||||
|
|
||||||
|
import { TagType, toggleListItem } from '../../../utils/showcase';
|
||||||
|
|
||||||
|
interface Props extends React.ComponentProps<"input"> {
|
||||||
|
icon: React.ReactElement<React.ComponentProps<"svg">>;
|
||||||
|
label: React.ReactNode;
|
||||||
|
tag: TagType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readSearchTags(search: string): TagType[] {
|
||||||
|
return new URLSearchParams(search).getAll("tags") as TagType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceSearchTags(search: string, newTags: TagType[]) {
|
||||||
|
const searchParams = new URLSearchParams(search);
|
||||||
|
searchParams.delete("tags");
|
||||||
|
newTags.forEach((tag) => searchParams.append("tags", tag));
|
||||||
|
return searchParams.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TagSelect = React.forwardRef<HTMLLabelElement, Props>(
|
||||||
|
({ id, icon, label, tag, ...rest }, ref) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const history = useHistory();
|
||||||
|
const [selected, setSelected] = React.useState(false);
|
||||||
|
React.useEffect(() => {
|
||||||
|
const tags = readSearchTags(location.search);
|
||||||
|
setSelected(tags.includes(tag));
|
||||||
|
}, [tag, location]);
|
||||||
|
const toggleTag = React.useCallback(() => {
|
||||||
|
const tags = readSearchTags(location.search);
|
||||||
|
const newTags = toggleListItem(tags, tag);
|
||||||
|
const newSearch = replaceSearchTags(location.search, newTags);
|
||||||
|
history.push({ ...location, search: newSearch });
|
||||||
|
}, [tag, location, history]);
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
className={`button button--sm button--outline button--secondary ${
|
||||||
|
selected ? "button--active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => {
|
||||||
|
toggleTag();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
{icon}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
33
website/src/pages/showcase/index.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useLocation } from '@docusaurus/router';
|
||||||
|
import Layout from '@theme/Layout';
|
||||||
|
|
||||||
|
import { Filters } from './_components/Filters';
|
||||||
|
import { Network } from './_components/Network';
|
||||||
|
import { Networks } from './_components/Networks';
|
||||||
|
|
||||||
|
const Showcase = (): JSX.Element => {
|
||||||
|
const location = useLocation();
|
||||||
|
const id = new URLSearchParams(location.search).get("id");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout
|
||||||
|
title="Showcase"
|
||||||
|
description="Portfolio of projects from the Meshtastic community"
|
||||||
|
>
|
||||||
|
<main className="margin-vert--lg">
|
||||||
|
{!!id ? (
|
||||||
|
<Network id={id} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Filters />
|
||||||
|
<Networks />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Showcase;
|
|
@ -1,37 +0,0 @@
|
||||||
/* stylelint-disable docusaurus/copyright-header */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
|
||||||
* and scoped locally.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.heroBanner {
|
|
||||||
padding: 4rem 0;
|
|
||||||
text-align: center;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 966px) {
|
|
||||||
.heroBanner {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 2rem 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featureImage {
|
|
||||||
height: 200px;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
125
website/src/utils/showcase.ts
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import { networks } from '../data/networks/_overview';
|
||||||
|
|
||||||
|
export interface Material {
|
||||||
|
name: string;
|
||||||
|
details: string;
|
||||||
|
image?: string;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Author {
|
||||||
|
name: string;
|
||||||
|
about: string;
|
||||||
|
url?: string;
|
||||||
|
avatarUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BodySegment {
|
||||||
|
heading: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkWriteup {
|
||||||
|
summary: string;
|
||||||
|
body: BodySegment[];
|
||||||
|
bom: Material[];
|
||||||
|
author: Author;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Tag = {
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TagType =
|
||||||
|
| "portable"
|
||||||
|
| "offGrid"
|
||||||
|
| "largeNetwork"
|
||||||
|
| "longDistance"
|
||||||
|
| "community"
|
||||||
|
| "favorite";
|
||||||
|
|
||||||
|
export interface Node {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShowcaseNetwork = {
|
||||||
|
id: string; //please get id from https://www.getuniqueid.com/cuid
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
nodes: Node[];
|
||||||
|
tags: TagType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Tags: Record<TagType, Tag> = {
|
||||||
|
portable: {
|
||||||
|
label: "Portable",
|
||||||
|
description: "Networks that move",
|
||||||
|
color: "#560bad",
|
||||||
|
},
|
||||||
|
|
||||||
|
offGrid: {
|
||||||
|
label: "Off Grid",
|
||||||
|
description: "No mains power here",
|
||||||
|
color: "#2a9d8f",
|
||||||
|
},
|
||||||
|
|
||||||
|
largeNetwork: {
|
||||||
|
label: "Large Network",
|
||||||
|
description: "Many users or nodes",
|
||||||
|
color: "#2191bc",
|
||||||
|
},
|
||||||
|
|
||||||
|
longDistance: {
|
||||||
|
label: "Long Distance",
|
||||||
|
description: "Links over massive distances",
|
||||||
|
color: "#e9c46a",
|
||||||
|
},
|
||||||
|
|
||||||
|
community: {
|
||||||
|
label: "Community",
|
||||||
|
description: "General access networks for many users",
|
||||||
|
color: "#e76f51",
|
||||||
|
},
|
||||||
|
|
||||||
|
favorite: {
|
||||||
|
label: "Favorite",
|
||||||
|
description: "Our picks for the coolest networks",
|
||||||
|
color: "#e9669e",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sortBy = <T>(array: T[], getter: (item: T) => unknown): T[] => {
|
||||||
|
const sortedArray = [...array];
|
||||||
|
sortedArray.sort((a, b) =>
|
||||||
|
getter(a) > getter(b) ? 1 : getter(b) > getter(a) ? -1 : 0
|
||||||
|
);
|
||||||
|
return sortedArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TagList = Object.keys(Tags) as TagType[];
|
||||||
|
function sortNetworks() {
|
||||||
|
let result = networks;
|
||||||
|
result = sortBy(result, (user) => user.title.toLowerCase());
|
||||||
|
result = sortBy(result, (user) => !user.tags.includes("favorite"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sortedNetworks = sortNetworks();
|
||||||
|
|
||||||
|
export const difference = <T>(...arrays: T[][]): T[] => {
|
||||||
|
return arrays.reduce((a, b) => a.filter((c) => !b.includes(c)));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleListItem = <T>(list: T[], item: T): T[] => {
|
||||||
|
const itemIndex = list.indexOf(item);
|
||||||
|
if (itemIndex === -1) {
|
||||||
|
return list.concat(item);
|
||||||
|
} else {
|
||||||
|
const newList = [...list];
|
||||||
|
newList.splice(itemIndex, 1);
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
};
|
BIN
website/static/img/hardware/rak/RAK11200.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
website/static/img/hardware/rak/RAK11310.png
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
website/static/img/hardware/rak/RAK12002.png
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
website/static/img/hardware/rak/RAK12003.png
Normal file
After Width: | Height: | Size: 242 KiB |
BIN
website/static/img/hardware/rak/RAK12004.png
Normal file
After Width: | Height: | Size: 457 KiB |
BIN
website/static/img/hardware/rak/RAK12005.png
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
website/static/img/hardware/rak/RAK12006.png
Normal file
After Width: | Height: | Size: 146 KiB |
BIN
website/static/img/hardware/rak/RAK12007.png
Normal file
After Width: | Height: | Size: 312 KiB |
BIN
website/static/img/hardware/rak/RAK12009.png
Normal file
After Width: | Height: | Size: 457 KiB |
BIN
website/static/img/hardware/rak/RAK12010.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
website/static/img/hardware/rak/RAK12011.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
website/static/img/hardware/rak/RAK12012.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
website/static/img/hardware/rak/RAK12015.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
website/static/img/hardware/rak/RAK12500.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
website/static/img/hardware/rak/RAK13001.png
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
website/static/img/hardware/rak/RAK13002.png
Normal file
After Width: | Height: | Size: 177 KiB |
BIN
website/static/img/hardware/rak/RAK13003.png
Normal file
After Width: | Height: | Size: 204 KiB |
BIN
website/static/img/hardware/rak/RAK13004.png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
website/static/img/hardware/rak/RAK13005.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
website/static/img/hardware/rak/RAK13101.png
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
website/static/img/hardware/rak/RAK14000.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
website/static/img/hardware/rak/RAK14001.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
website/static/img/hardware/rak/RAK14002.png
Normal file
After Width: | Height: | Size: 212 KiB |
BIN
website/static/img/hardware/rak/RAK14003.png
Normal file
After Width: | Height: | Size: 146 KiB |
BIN
website/static/img/hardware/rak/RAK15000.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
website/static/img/hardware/rak/RAK15001.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
website/static/img/hardware/rak/RAK15002.png
Normal file
After Width: | Height: | Size: 176 KiB |
BIN
website/static/img/hardware/rak/RAK16000.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
website/static/img/hardware/rak/RAK16001.png
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
website/static/img/hardware/rak/RAK17000.png
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
website/static/img/hardware/rak/RAK18000.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
website/static/img/hardware/rak/RAK18001.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
website/static/img/hardware/rak/RAK19002.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
website/static/img/hardware/rak/RAK19003.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
website/static/img/hardware/rak/RAK19004.png
Normal file
After Width: | Height: | Size: 613 KiB |
BIN
website/static/img/hardware/rak/RAK19005.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
website/static/img/hardware/rak/RAK19006.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
website/static/img/hardware/rak/RAK19008.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
website/static/img/hardware/rak/RAK1901.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
website/static/img/hardware/rak/RAK1902.png
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
website/static/img/hardware/rak/RAK1903.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
website/static/img/hardware/rak/RAK1904.png
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
website/static/img/hardware/rak/RAK1906.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
website/static/img/hardware/rak/RAK1910.png
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
website/static/img/hardware/rak/RAK1920.png
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
website/static/img/hardware/rak/RAK1921.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
website/static/img/hardware/rak/RAK2305.png
Normal file
After Width: | Height: | Size: 402 KiB |
BIN
website/static/img/hardware/rak/RAK4631.png
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
website/static/img/hardware/rak/RAK5005-O.png
Normal file
After Width: | Height: | Size: 217 KiB |
BIN
website/static/img/hardware/rak/RAK5801.png
Normal file
After Width: | Height: | Size: 532 KiB |
BIN
website/static/img/hardware/rak/RAK5802.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
website/static/img/hardware/rak/RAK5804.png
Normal file
After Width: | Height: | Size: 146 KiB |
BIN
website/static/img/hardware/rak/RAK5811.png
Normal file
After Width: | Height: | Size: 426 KiB |
BIN
website/static/img/hardware/rak/RAK5860.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
website/static/img/hardware/t-echo-lilygo.jpg
Normal file
After Width: | Height: | Size: 101 KiB |
|
@ -1,4 +1,8 @@
|
||||||
{
|
{
|
||||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
"include": ["src/"]
|
"include": ["src/"]
|
||||||
}
|
}
|
||||||
|
|