WIP showcase loader

This commit is contained in:
Sacha Weatherstone 2021-12-03 13:09:13 +11:00
parent ca8793279f
commit c7cad7143d
11 changed files with 447 additions and 105 deletions

View file

@ -0,0 +1,104 @@
# Meshtastic 1.1 feature list ideas
This is a collection of ideas for post 1.0 features. Based on community input we can tweak this list. Please add (but do not delete) ideas you are interested in. Feel free to add details/comments/links to **the bottom** of these lists, then post in [this thread](https://meshtastic.discourse.group/t/the-1-1-feature-work-list-triage-thread-lobby-for-your-features-here/1324) so we can discuss how to prioritize.
We have two approximate buckets: 1.1 features (next threeish months?) and 1.5 features (next sixish months). Mostly the focus now is on selecting which of the proposed 1.1 ideas developers actually want to work on. So please don't feel bad if your idea isn't high on this list, instead post in the linked thread and hopefully one of our volunteer devs will get excited to work on it. Or if you'd like to learn how to be a dev, we can mentor you through a github issue or on our slack channel.
But of course if someone wants to work on something (even if not in this list, or if it is low) work on it and have fun. We will happily merge pull-requests as possible.
## New device features
( @geeksville will probably spend about 60% of his time on these new features, and about 40% bug fixing / clean-up over the next two-three months)
Probably in 1.1:
* Implement router mode - for super long battery life / low power consumption solar nodes. (See issue #377).
* Finish RAK815 support (to prove that low ram NRF52 devices are fully supported)
* Wifi AP or STA mode support and serve up the meshtastic API on a TCP port (@mc-hamster is working on this)
* MQTT protocol/gateway so nodes(And other devices) can communicate through internet if they have an AP.(See issue #377)
* Use MQTT layer to allow remote GPIO control
* Use MQTT layer to allow text messaging gateway via the internet and riot.im.
* Any node in the mesh that has internet connectivity (via direct wifi or via connected PC/phone) will route MQTT for other nodes. #8
* Use the new named-attribute feature to make a 'remote GPIO' on device app, for easy remote control/monitoring of GPIOs with no custom code required. #182
* Port meshtastic to the Pinetab lora radio (this would also allow meshtastic to run on most Posix targets) #143
* Support totally opaque payloads, for use with really low end MCUs ( https://github.com/meshtastic/Meshtastic-device/issues/383 )
* Port meshtastic to very exciting boards I've been told about.
* When battery voltage falls below TBD threshold, change network params to maximize battery life and ensure we can still be contacted by radio if needed. (especially useful for solar powered router nodes) (T-Beam needs power-up default, at present they need a button press to start, not useful for unattended repeater)
* Add power profiles to the device, which can be set from the android app. See [Issue 389](https://github.com/meshtastic/Meshtastic-device/issues/389) - A small number of presets to simplify the selection of the device's power saving features.
Probably later:
* iOS client (probably via Flutter?)
* Implement a 'I need emergency help button' #60
* Make a new 'geofencing' on device app, which messages when a node enters/leaves a place. Could allow **very** long battery life for animal tracking.
* Store and forward messaging - If the mesh gets fragmented or a node goes out of range for x-period of time, eventually deliver the messages to the node that has rejoined. Especially useful for the hiking use case because someone may be over a ridge and have lost the Line of Sight.
* TTGO v2.0 2.1 navigation buttons soldered on the board(ability to customize button gpios via preferences)
* Extend the portduino simulator to run whole meshes of nodes in simulation.
* Enable a specific node in the mesh to log all position packets to a file (either in the App or SD card on device) to allow post activity route analysis of each node
* Buzzer support: Beeps for message received, node join, low battery etc
* Let user subscribe to multiple channels at once
* show compass heading in degrees as well as arrow. Makes it easier to track the true direction of a person in distress.
* add text-to-speech option in the app, for hands/screen free monitoring (while busy with stuff) and warnings of system events (new node discovered, low battery etc...)
* add speech-to-text to the app, now it can be used almost as a normal phone.
* External buttons - Have firmware recognise several exposed GPIO pins for 'scroll', 'event', etc. so that external mom.spst (reed sw, mercury sw. etc) can trigger these events. At present, we must expose device to the elements, or manufacture weatherproof actuators (difficult).
* Let app distribute APKs of itself over bluetooth or wifi: per [this forum post](https://meshtastic.discourse.group/t/suggestion-ability-to-transfer-app-apk-to-another-android-device-via-bt-or-other-non-network-dependent-method/711). let the device distribute the app or have a wifi web client for basic use for any wifi enabled device.
* Rearrange tabs on screen and add sorting option by name, range, battery, etc. See [Issue 387](https://github.com/meshtastic/Meshtastic-device/issues/387)
* Keyboard feature: Either connect a bluetooth or I2C cheap keyboard or use T-Beam buttons to select characters(One button select letters A-Z and the other one is the Next button.If you hold the next button down it will transmit the message)
Probably much-much later (or never? unless someone wants to do this):
* Code to support TTGO T-Dear mini, TTGO T-SOLAR, Lora32u4 II, Heltec Cube.Features: Recognise a relay in the nodeList as a relay.Ability to redirect all channels or only a list of channels.Have an owner password in order to change settings on the go(Like allowed channels name and battery status usage view etc).It should have a mode that it's used by the owner to map it's range. (@geeksville comment: I know of a couple of upcoming products that I think will make all of these 'ASR6505 based' low RAM devices obsolete. i.e. same price (approx), much more RAM and flash, even lower power consumption. So I don't recommend spending much time on this idea)
* Implement TTN LoraWan communication for messages and for 'I need emergency help button' #60 #377 (@geeksville comment: I think once we add our MQTT gateway/routing feature, there is minimal need for this case - given that TTN coverage is far lower than what meshtastic can achieve by letting any node gateway if it can get wifi or 4G)
* Stealth Mode: Fully disable GPS and location services to increase privacy. (I think this is already mentioned somewhere, can't find a link)
## Plumbing ideas
Not user visible but useful for the future.
Probably in 1.1:
* Clean up the device code - make the 'mesh' layer a separate library. Split the current gui into an on device 'app'
* Minor code cleanups, bugs #108, #107
* Portduino: meshtastic for base Posix (non arduino) systems.
* Add real power-on and factory diags, to detect failed hardware #128
Probably later:
* Report device crashes via the android analytics pipe
* Revisit the power measurements on ESP32 and NRF52 and retune, confirm new battery life
* Use the MQTT gateway to let users (optionally) upload signal strength and position info, so we can build a corpus of real-world measured radio performance
## App Ideas
These are ideas for the Android app. If anyone wants to make an iOS client (possibly based on [Flutter](https://flutter.dev/) @geeksville is happy to help you succeed)
Ideas for the meshtastic App development
Probably in 1.1:
* Make a tablet specific layout (I forget the bug number) - that shows map and chat at the same time
* Enable landscape layout (I forget the bug number)
* Tap on failed message to re-send them
* Implement Ping button for each node in the app list in order to refresh details about the position and the signal strength.
* Display nodes Rssi connection status with other nodes (It would be cool to see the RSSI on the map for each node from the entire network(This can be called to diagnose the network and has to be done through a button press in order to get this info when it's needed).This would help to extend coverage in the area)
* Notifications when node joins your network.
* Set wifi SSID PASSWORD, MQTT SERVER IP, power profiles #389 from the app. Probably best done by using reflection to get various settings names.
Probably later:
* Whatsapp Style communication system with full name display and correct message positioning(Sender's messages in the right and receiver's message in the left)
* Different icons for different node models, different icons for the nodes that are connected to the internet to suggest internet and mqtt connection, also more info on the "People" section(second tab from the left): RSSI, Board Info, Wifi Access, MQTT Access.
* Allow the sharing of static GPS Waypoints that would be plotted on the application map such as: Meeting locations, First AID, Water source, Vista, etc.
# 1.5 feature ideas
This is the next big bucket after 1.1. Probably dropping about six months from now. Biggest work item is probably switching to qmesh or reticulum as our transport (or possibly staying with the current transport and optimizing).
## Protocol ideas
* Use an alternative routing protocol (Reticulum, QMesh) #192
* Fully implement DSR for unicast messages #3 (if we don't switch to a different transport)
* Allow nodes to route for channels they don't have the encryption keys for
* Programmatically limit duty cycles for regulatory compliance
* Since nodes have GPS time, leave all receivers (and CPUs) completely off most of the time - then once every 30secs, wake and check to see if anyone is transmitting)

View file

@ -0,0 +1,66 @@
If you have not already done so, download and have the latest firmware for your device, and flash it to your device.
There is a very good guide for doing this [here](https://github.com/meshtastic/Meshtastic-device#firmware-installation).
Part of this guide covers the installation of pip which must be done first.
**For Linux users:**
From a terminal copy and paste the following command
```bash
pip3 install meshtastic
```
**For Windows users:**
_Insert instructions on how to install meshtastic here_
**For Mac OS users:**
_Insert instructions on how to install meshtastic here_
Using a text editor, open a blank document and copy and paste the following text
```bash
#/bin/sh
clear
echo "Set all Router Parameter"
meshtastic --setowner MeshRelay
meshtastic --settime
meshtastic --set is_router true
meshtastic --setlat 53.9 --setlon -6.8 --setalt 91
meshtastic info
```
Alter the parameter `meshtastic --setowner MeshRelay` and change "MeshRelay" to your chosen name
This will set the name of the relay.
Alter the parameter `meshtastic --setlat 53.9 --setlon -6.8 --setalt 91`
This parameter sets the latitude, longitude and altitude of your relay, assuming it doesnt have a working or installed GPS. If you have a working GPS, the device will connect to a GPS satellite and update the latitude, longitude and altitude.
Using this site, find the location of where you plan to place your relay.
[Get latitude, longitude and altitude](https://www.maps.ie/coordinates.html)
Move the place marker over the spot where your relay is to placed, and it will give you the latitude, longitude and altitude.
Enter the latitude and longitude to one decimal place and altitude is recorded in metres in the configuration file.
As a suggestion, save the configuration file into the same folder, where you have downloaded the latest device firmware.
Save the file as `relay.sh`
Go to the folder where you have saved the script and right click on "Open in Terminal"
At the command prompt in Terminal, enter the following command
```bash
sudo chmod -R 777 relay.sh
```
This enables the script to be executed as a program.
Then at the prompt enter: `./relay.sh`
That's it, your Meshtastic device is now configure to operate as a relay.
**Some explanations of other parameters**
`meshtastic --set is_router true` tells node to be power conscious and to only power up the screen/BLE if the user presses a button. Eventually will also imply that "this node has good line of sight and should be heavily weighted when routing". This is the option you should probably use.
`meshtastic --set is_low_power true`. This option means "work like a regular node, with the normal sleep/wake pattern but even though you see power coming in on USB dont constantly stay awake". You **almost certainly don't want this option** but it is useful for some edge cases (solar powered node that still talks Bluetooth to the app etc...).

View file

@ -18,7 +18,8 @@
"@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",
"react-dom": "^17.0.2" "react-dom": "^17.0.2",
"react-icons": "^4.3.1"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

View file

@ -1,80 +1 @@
import { ShowcaseNetwork } from '../../utils/showcase'; export const writeups: string[] = ["ckwhq3l5a000008kufkw8f3dg"];
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"],
},
];

View file

@ -0,0 +1,109 @@
import { NetworkWriteup, ShowcaseNetwork } from '../../utils/showcase';
import { rakWireless } from '../hardware/rakWireless';
export const metadata: ShowcaseNetwork = {
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"],
};
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: "",
},
};

View file

@ -1,6 +1,28 @@
import { NetworkWriteup } from '../../../utils/showcase'; import { NetworkWriteup, ShowcaseNetwork } from '../../../utils/showcase';
import { rakWireless } from '../../hardware/rakWireless'; import { rakWireless } from '../../hardware/rakWireless';
export const metadata: 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"],
};
export const writeup: NetworkWriteup = { export const writeup: NetworkWriteup = {
summary: "This is the article summary.", summary: "This is the article summary.",
body: [ body: [

View file

@ -0,0 +1,93 @@
import React from 'react';
import Layout from '@theme/Layout';
const Firmware = (): JSX.Element => {
return (
<Layout
title="Firmware"
description="Firmware download for the Meshtastic project"
>
<main className="margin-vert--xl">
<div className="container">
{/* */}
<div
className="margin-bottom--sm"
style={{
display: "flex",
alignItems: "center",
}}
>
<h2>Stable</h2>
</div>
<ul
style={{
position: "relative",
display: "grid",
gap: "1.5rem",
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
paddingLeft: "0",
}}
>
{/* */}
<div className="card">
<div className="card__header">
<h3>Beta</h3>
</div>
<div className="card__body">
<p>Tested feature set. For those who want stability.</p>
</div>
<div className="card__footer">
<button className="button button--secondary button--block">
See All
</button>
</div>
</div>
{/* */}
{/* */}
<div className="card">
<div className="card__header">
<h3>Alpha</h3>
</div>
<div className="card__body">
<p>
Upcomming changes for testing. For those who want new
features.
</p>
</div>
<div className="card__footer">
<button className="button button--secondary button--block">
See All
</button>
</div>
</div>
{/* */}
{/* */}
<div className="card">
<div className="card__header">
<h3>Bleeding</h3>
</div>
<div className="card__body">
<p>
Latest successful CI build. For those who want to break
things.
</p>
</div>
<div className="card__footer">
<button className="button button--secondary button--block">
See All
</button>
</div>
</div>
{/* */}
</ul>
</div>
</main>
</Layout>
);
};
export default Firmware;

View file

@ -1,29 +1,31 @@
import React from 'react'; import React from 'react';
import { networks } from '../../../data/networks/_overview'; // import { networks } from '../../../data/networks/_overview';
import { NetworkWriteup } from '../../../utils/showcase'; import { NetworkWriteup, ShowcaseNetwork } from '../../../utils/showcase';
interface NetworkProps { interface NetworkProps {
id: string; id: string;
} }
export const Network = ({ id }: NetworkProps): JSX.Element => { export const Network = ({ id }: NetworkProps): JSX.Element => {
import(`../../../data/networks/${id}/writeup.ts`).then((data) => { import(`../../../data/networks/${id}`).then((data) => {
setNetworkWriteup(data.writeup as NetworkWriteup); setNetworkWriteup(data.writeup as NetworkWriteup);
setMetadata(data.metadata as ShowcaseNetwork);
}); });
// console.log(data); // console.log(data);
const [networkWriteup, setNetworkWriteup] = React.useState<NetworkWriteup>(); const [networkWriteup, setNetworkWriteup] = React.useState<NetworkWriteup>();
const [metadata, setMetadata] = React.useState<ShowcaseNetwork>();
React.useEffect(() => { React.useEffect(() => {
// data.then((data) => setNetworkWriteup(data)); // data.then((data) => setNetworkWriteup(data));
}, []); }, []);
const network = networks.find((network) => network.id === id); // const network = networks.find((network) => network.id === id);
return network && networkWriteup ? ( return metadata && networkWriteup ? (
<div className="container"> <div className="container">
<h1>{network.title}</h1> <h1>{metadata.title}</h1>
<p>{network.description}</p> <p>{metadata.description}</p>
<div className="avatar"> <div className="avatar">
<img <img
src={networkWriteup.author.avatarUrl} src={networkWriteup.author.avatarUrl}

View file

@ -7,13 +7,6 @@ import { useSelectedTags } from '../../../hooks/useSelectedTags';
import { ShowcaseNetwork, sortedNetworks } from '../../../utils/showcase'; import { ShowcaseNetwork, sortedNetworks } from '../../../utils/showcase';
import { Card } from './Card'; import { Card } from './Card';
const favoriteNetworks = sortedNetworks.filter((network) =>
network.tags.includes("favorite")
);
const otherNetworks = sortedNetworks.filter(
(network) => !network.tags.includes("favorite")
);
interface NetworkSectionProps { interface NetworkSectionProps {
title: string; title: string;
icon?: JSX.Element; icon?: JSX.Element;
@ -70,6 +63,16 @@ const NetworkSection = ({
}; };
export const Networks = (): JSX.Element => { export const Networks = (): JSX.Element => {
const [sorted, setSorted] = React.useState<ShowcaseNetwork[]>([]);
const [other, setOther] = React.useState<ShowcaseNetwork[]>([]);
sortedNetworks.then((networks) => {
setSorted(networks.filter((network) => network.tags.includes("favorite")));
});
sortedNetworks.then((networks) => {
setOther(networks.filter((network) => !network.tags.includes("favorite")));
});
const selectedTags = useSelectedTags(); const selectedTags = useSelectedTags();
const filteredNetworks = useFilteredNetworks(); const filteredNetworks = useFilteredNetworks();
@ -81,9 +84,9 @@ export const Networks = (): JSX.Element => {
title="Our favorites" title="Our favorites"
icon={<FiHeart />} icon={<FiHeart />}
iconColor="rgb(190 24 93)" iconColor="rgb(190 24 93)"
networks={favoriteNetworks} networks={sorted}
/> />
<NetworkSection title="All networks" networks={otherNetworks} /> <NetworkSection title="All networks" networks={other} />
</> </>
) : ( ) : (
<NetworkSection <NetworkSection

View file

@ -1,4 +1,4 @@
import { networks } from '../data/networks/_overview'; import { writeups } from '../data/networks/_overview';
export interface Material { export interface Material {
name: string; name: string;
@ -100,12 +100,28 @@ export const sortBy = <T>(array: T[], getter: (item: T) => unknown): T[] => {
}; };
export const TagList = Object.keys(Tags) as TagType[]; export const TagList = Object.keys(Tags) as TagType[];
function sortNetworks() { const sortNetworks = async (): Promise<ShowcaseNetwork[]> => {
let result = networks; const metadata = await Promise.all(
result = sortBy(result, (user) => user.title.toLowerCase()); writeups.map(async (id) => {
result = sortBy(result, (user) => !user.tags.includes("favorite")); const data = (await import(`../data/networks/${id}`)) as {
return result; metadata: ShowcaseNetwork;
} writeup: NetworkWriteup;
};
return data.metadata;
})
);
let sorted = sortBy(metadata, (network) => network.title.toLowerCase());
return (sorted = sortBy(
sorted,
(network) => !network.tags.includes("favorite")
));
// 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 sortedNetworks = sortNetworks();

View file

@ -6775,6 +6775,11 @@ react-helmet@^6.1.0:
react-fast-compare "^3.1.1" react-fast-compare "^3.1.1"
react-side-effect "^2.1.0" react-side-effect "^2.1.0"
react-icons@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"