diff --git a/.github/workflows/deploy-next.yml b/.github/workflows/deploy-next.yml index f439bcb..d9c090a 100644 --- a/.github/workflows/deploy-next.yml +++ b/.github/workflows/deploy-next.yml @@ -15,6 +15,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: 'recursive' + fetch-depth: 0 - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index 9672ea5..aa378b6 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -15,6 +15,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: 'recursive' + fetch-depth: 0 - uses: actions/setup-node@v3 with: diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8110a10 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "ext/toit-lightbug"] + path = ext/toit-lightbug + url = https://github.com/lightbug-io/toit-lightbug.git +[submodule "ext/toit-ide-tools"] + path = ext/toit-ide-tools + url = https://github.com/toitware/ide-tools diff --git a/.vitepress/config.mts b/.vitepress/config.mts index dac7a66..6bfec3a 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -7,6 +7,13 @@ import { loadSpec } from '../swagger/load'; import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'; import { pagefindPlugin } from 'vitepress-plugin-pagefind'; import { withMermaid } from "vitepress-plugin-mermaid"; +import { imgSize } from "@mdit/plugin-img-size"; +import { figure } from "@mdit/plugin-figure"; +import { attrs } from "@mdit/plugin-attrs"; +import { align } from "@mdit/plugin-align"; +import { include } from "@mdit/plugin-include"; +import { withSidebar, generateSidebar } from 'vitepress-sidebar'; +import yamlEmbed from '../utils/markdownit-yaml-plugin.js'; // Load protocol messages from YAML file @@ -46,21 +53,86 @@ const protocolMenuItems = Object.keys(protocolGroups) // Ability to generate other collections of side bar entries const sidebarItemsFromDir = (dir) => { const files = fs.readdirSync(dir) - return files - .filter(file => file !== 'index.md') - .map(file => { - const name = file.replace('.md', '') - const displayName = name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, ' '); - return { - text: displayName, - link: `${dir}/${name}` + .filter(file => file !== 'index.md' && file.endsWith('.md')) + + const items = files.map(file => { + const fullPath = path.resolve(dir, file); + let order = 100; + try { + const content = fs.readFileSync(fullPath, 'utf8'); + // simple frontmatter parse: look for leading --- yaml --- block + const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (fmMatch) { + const fm = yaml.load(fmMatch[1]); + if (fm && typeof fm.order === 'number') { + order = fm.order; + } } - }) + } catch (e) { + // ignore and use default order + } + + const name = file.replace('.md', '') + const displayName = name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, ' '); + return { + text: displayName, + link: `${dir}/${name}`, + order, + } + }) + + // sort by order, then by text + items.sort((a, b) => { + if (a.order !== b.order) return a.order - b.order; + return a.text.localeCompare(b.text); + }); + + // remove the temporary order field before returning + return items.map(({ order, ...rest }) => rest) } const sidebarSpec1 = useSidebar({ spec: loadSpec(1) }); const sidebarSpec2 = useSidebar({ spec: loadSpec(2) }); +// Generate Admin Actions sidebar automatically using vitepress-sidebar +const generateAdminDevicesSidebar = () => { + // Helper function to fix links recursively + const fixLinks = (items, prefix = '/apps/admin/devices') => { + return items.map(item => { + const newItem = { ...item }; + + // Fix the link if it exists and doesn't already start with the prefix + if (newItem.link && !newItem.link.startsWith(prefix)) { + newItem.link = prefix + (newItem.link.startsWith('/') ? '' : '/') + newItem.link; + } + + // Recursively fix nested items + if (newItem.items) { + newItem.items = fixLinks(newItem.items, prefix); + } + + return newItem; + }); + }; + + // Use vitepress-sidebar to auto-generate the entire devices section + const devicesSidebar = generateSidebar({ + documentRootPath: '/', + scanStartPath: 'apps/admin/devices', + hyphenToSpace: true, + capitalizeFirst: true, + useTitleFromFrontmatter: true, + sortMenusByFrontmatterOrder: true, + frontmatterOrderDefaultValue: 100, + includeRootIndexFile: false, + includeFolderIndexFile: false, + useFolderLinkFromIndexFile: true, + }); + + const fixedSidebar = Array.isArray(devicesSidebar) ? fixLinks(devicesSidebar) : devicesSidebar; + return fixedSidebar as any; +}; + // Function to make a sidebar group be collapsed function collapse(group) { group.collapsed = true; @@ -94,6 +166,9 @@ export default withMermaid(defineConfig({ description: "home for everything Lightbug", lang: 'en-GB', cleanUrls: true, + sitemap: { + hostname: process.env.DEPLOYMENT_NAME === 'Production' ? 'https://docs.lightbug.io' : 'https://docs-next.lightbug.io' + }, rewrites: { '/onprem/' : '/silos/', }, @@ -113,7 +188,35 @@ export default withMermaid(defineConfig({ markdown: { config: (md) => { md.use(tabsMarkdownPlugin) + md.use(imgSize) + md.use(figure) + md.use(attrs) + md.use(align) + // Embed YAML values from files during markdown parsing to avoid Vue + // interpolation errors for `{{yaml:...}}` tokens. + md.use(yamlEmbed, { baseDir: path.resolve(__dirname, '..', 'public', 'files') }) + md.use(include,{ + currentPath: () => { + return path.resolve(__dirname, '..', 'index.md'); + }, + }) }, + languages: (() => { + try { + const toitGrammar = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../ext/toit-ide-tools/vscode/syntaxes/toit.tmLanguage.json'), 'utf8')); + + const toitLang = { + ...toitGrammar, + id: 'toit', + aliases: ['toit'] + }; + + return [toitLang]; + } catch (error) { + console.error('Error loading Toit grammar:', error); + return []; + } + })(), container: { tipLabel: '⚡ Tip', warningLabel: '⚠️ Warning', @@ -138,6 +241,23 @@ export default withMermaid(defineConfig({ gtag('js', new Date()); gtag('config', '${process.env.PUBLIC_GOOGLE_ANALYTICS}');` ] + , + [ + 'link', + { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' } + ], + [ + 'link', + { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' } + ], + [ + 'link', + { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' } + ], + [ + 'link', + { rel: 'manifest', href: '/site.webmanifest' } + ], ], themeConfig: { // https://vitepress.dev/reference/default-theme-config @@ -190,8 +310,17 @@ export default withMermaid(defineConfig({ { text: 'General', items: [ + { + text: 'Positioning', + link: '/terminology/positioning/', + items: [ + { text: 'GNSS', link: '/terminology/positioning/gnss' }, + { text: 'RTK', link: '/terminology/positioning/rtk' }, + { text: 'WiFi', link: '/terminology/positioning/wifi' }, + { text: 'Cellular', link: '/terminology/positioning/cellular' }, + ] + }, { text: 'IoT', link: '/terminology/iot' }, - { text: 'Positioning', link: '/terminology/positioning' }, { text: 'Observability', link: '/terminology/observability' }, ] }, @@ -241,10 +370,23 @@ export default withMermaid(defineConfig({ text: 'Enviro', link: '/devices/enviro/', }, + ] + }, + { + text: 'RTK', + items: [ { - text: 'RTK', - link: '/devices/rtk/', + text: 'Handheld', + link: '/devices/rtk/handheld/', + collapsed: true, + items: [ + { text: 'External', link: '/devices/rtk/handheld/external' }, + { text: 'Screen', link: '/devices/rtk/handheld/screen' }, + { text: 'ESP32', link: '/devices/rtk/handheld/esp32' }, + { text: 'Accessories', link: '/devices/rtk/handheld/accessories' }, + ] }, + { text: 'Vehicle', link: '/devices/rtk/vehicle' }, ] }, { @@ -257,7 +399,7 @@ export default withMermaid(defineConfig({ }, { text: 'Lineage', - link: '/devices/history', + link: '/devices/history/', collapsed: true, items: [ { text: 'VT2', link: '/devices/history/VT2' }, @@ -288,34 +430,48 @@ export default withMermaid(defineConfig({ link: '/devices/api/glossary', }, { - text: 'Structure', - collapsed: true, - link: '/devices/api/structure', + text: 'Toit', + link: '/devices/api/sdks/toit/', + items: [ + { text: 'Getting Started', link: '/devices/api/sdks/toit/getting-started' }, + { + text: 'Examples', + link: '/devices/api/sdks/toit/examples/', + items: sidebarItemsFromDir('devices/api/sdks/toit/examples') + }, + ], + }, + { + text: 'Messages', + link: '/devices/api/messages', + items: protocolMenuItems, + }, + { + text: 'Protocol', + link: '/devices/api/protocol/', items: [ { text: 'Prefix', - link: '/devices/api/structure#prefix', + link: '/devices/api/protocol/prefix', + }, + { + text: 'Stop', + link: '/devices/api/protocol/stop', + }, + { + text: 'Structure', + link: '/devices/api/protocol/structure', }, { - text: 'Message', - link: '/devices/api/structure#message', + text: 'Headers', + link: '/devices/api/protocol/headers', }, { text: 'Examples', - link: '/devices/api/structure#examples', + link: '/devices/api/protocol/examples', }, ] }, - { - text: 'Headers', - link: '/devices/api/headers', - }, - { - text: 'Messages', - collapsed: true, - link: '/devices/api/messages', - items: protocolMenuItems, - }, { text: 'Tools', collapsed: true, @@ -334,26 +490,6 @@ export default withMermaid(defineConfig({ }, ] }, - { - text: 'SDKs', - collapsed: true, - items: [ - { - text: 'Toit', - link: '/devices/api/sdks/toit/', - items: [ - { text: 'Getting Started', link: '/devices/api/sdks/toit/getting-started' }, - { - text: 'Examples', - link: '/devices/api/sdks/toit/examples/', - items: [ - { text: 'EInk Hello World', link: '/devices/api/sdks/toit/examples/eink' }, - ] - }, - ], - }, - ] - }, ] }, ], @@ -630,12 +766,7 @@ export default withMermaid(defineConfig({ ] }, { text: 'Devices', link: '/apps/admin/devices', // No ending /, as the sub items are not sub pages - items: [ - { text: 'Actions', link: '/apps/admin/devices#actions' }, - { text: 'Metrics', link: '/apps/admin/devices#metric-summary' }, - { text: 'Timeline', link: '/apps/admin/devices#timeline' }, - ] - + items: generateAdminDevicesSidebar() }, { text: 'Configs', link: '/apps/admin/configs' }, { text: 'Users', link: '/apps/admin/users' }, diff --git a/.vitepress/theme/Layout.vue b/.vitepress/theme/Layout.vue index 262f49e..b60ef6b 100644 --- a/.vitepress/theme/Layout.vue +++ b/.vitepress/theme/Layout.vue @@ -17,6 +17,8 @@ const redirects = Object.entries({ '/devices/api/generate': '/devices/api/tools/generate', '/apps/admin/creating-account': '/apps/admin/authentication#creating-an-account', '/apps/admin/permissions': '/apps/admin/authentication#permissions', + '/devices/api/structure': '/devices/api/protocol', + '/devices/api/headers': '/devices/api/protocol/headers', }) watch( diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index 159decf..e0b6542 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -19,3 +19,30 @@ .VPSidebarItem.level-0 { padding-bottom: 10px !important; } + +/* A generic class to center things, mainly images */ +.center { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} +figure:has(> img.center) { + text-align: center; +} + +/* ----------------------------------------------- */ +/* Custom default tab styling... */ +/* ----------------------------------------------- */ + +/* +Custom TAB styling, when the tab is called "Mobile" +Screenshots of mobile devices are not that wide +So we want to limit their height (as they are tall), and center them +*/ +[id^="panel-Mobile-"].plugin-tabs--content[role="tabpanel"] img { + display: block; + margin-left: auto; + margin-right: auto; + max-height: 354.719px; /* Based on desktop image that was 1424x770 */ +} diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 3755ba3..a7c7e81 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -9,6 +9,8 @@ import * as directives from 'vuetify/directives' import { createVuetify } from 'vuetify' import { VStepperVertical } from 'vuetify/labs/VStepperVertical' import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader +import 'eva-icons/style/eva-icons.css' +import * as eva from 'eva-icons' import { createVCodeBlock } from '@wdns/vue-code-block'; import 'vitepress-openapi/dist/style.css' @@ -38,10 +40,15 @@ export default { enhanceAppWithTabs(app) + // Initialize Eva Icons + if (typeof window !== 'undefined') { + eva.replace() + } + // Setup Theme const themeConfig = useTheme() themeConfig.setI18nConfig({ locale: 'en' }) themeConfig.setResponseCodeSelector('select') - theme.enhanceApp({ app }) + theme.enhanceApp({ app, router, siteData }) } } satisfies Theme diff --git a/apps/admin/authentication.md b/apps/admin/authentication.md index d2de26b..de06c8f 100644 --- a/apps/admin/authentication.md +++ b/apps/admin/authentication.md @@ -21,7 +21,7 @@ On successful account creation, you will be directed to the login page. After creating your main account, you can add sub accounts to share device access with others from the admin portal. -For more details, see [adding new users to devices](/apps/admin/devices#add-new-user). +For more details, see [adding new users to devices](/apps/admin/devices/users#add-new-user). ## Logging In @@ -53,6 +53,6 @@ Different permissions will reveal different interfaces in the side bar, as well | Page | user | trackerAdmin |Description | | -- | -- | -- | -- | -| [Devices](./devices.html) | ✅ | ✅ |List all devices on the account| +| [Devices](/apps/admin/devices/) | ✅ | ✅ |List all devices on the account| | [Configs](./configs.html) | |✅ |Manage `config pages` that can be applied to devices| | [Users](./users.html) | |✅ |Manage sub users of your account| diff --git a/apps/admin/devices.md b/apps/admin/devices.md deleted file mode 100644 index d10719b..0000000 --- a/apps/admin/devices.md +++ /dev/null @@ -1,248 +0,0 @@ ---- -outline: deep ---- -# Devices - -The default view is the device list, which shows all devices in the account. - -![Lightbug Admin device list](https://i.imgur.com/pHBzHGL.png) - - -## Fields - -The device list shows the following fields: -- Identifiers: Static [identifiers](/terminology/devices#identity) for the device. - - ID - - Serial Number - - IMEI - - ICCID -- Names - - Name: User defined name for the device. - - Type: Device type, such as `ZeroN` etc. - - Tags: User defined [tags](/terminology/devices#tags) for the device. -- Seen - - Last: Time the device was last seen by the Lightbug platform, this may not be a 1:1 match with when data was last received. - - First: Time the device was fist seen by the Lightbug platform, likely around the time it was manufactured. -- Users -- Plan details -- Firmware -- Status - - Battery - - Enabled -- [Actions](#actions) - -## Filters - -Filters can be used to narrow down the list of devices. - -Such as all `ZeroN` devices. - -![](https://i.imgur.com/JkdXTz6.png) - -## Actions - -The devices table has a number of actions that can be performed on devices, either in row actions, or via buttons on the right hand side of the rows, or via bulk actions having multiple devices selected. - -### In row actions - -Some actions are available on the device list itself, by interacting with various fields. - -#### Reveal ICCID & IMEI - -Click the `(more)` link in the identifiers column to reveal the ICCID and IMEI of the device. - -![](https://i.imgur.com/xoTN8ga.png) - -#### Set device name - -Hovering over a device name will reveal a pencil icon, which can be clicked to edit the device name. - -Hit `Enter` to save the new name, or `Escape` to cancel. - -![](https://i.imgur.com/22CIjYw.png) - -#### Schedule Firmware Update - -Clicking on the firmware version will open a dialog allowing you to schedule a firmware update for the device. - -![](https://i.imgur.com/sK66Th6.png) - -### Button Actions - -Some per device actions are available via buttons on the right hand side of the rows, these are: - -![](https://i.imgur.com/vOxhOLt.png) - -- Activate / Deactivate -- [Manage Users](#manage-users) -- Manage Settings -- [See Device information](#device-information) -- [Manage Forwarding](#manage-forwarding) - -#### Manage Users - -Clicking on the manage users icon will open a dialog allowing you to add or remove users from the device. - -Users can have different global permissions, which can be controlled from the [users page](/apps/admin/users#permissions). - -![](https://i.imgur.com/yIbkNpT.png) - -Clicking `Add User`, open an additional dialog allowing you to select a user from the list of users on your account, or create a new user. - -##### Add Existing user - -In order to select an existing user, click on their name from the list. - -![](https://i.imgur.com/5aFeQlp.png) - -On success, you'll see a confirmation message in the top right corner. - -:::warning -If the user already exists, and they are not a sub user of your account, you will not be able to select them. -If this is the case please contact support to get them added to your account. -::: - -##### Add New user - -To create a new user, click on the `Create New` button. - -This will open a dialog allowing you to enter the new users details. - -![](https://i.imgur.com/QEnoQwF.png) - -Once you have entered the details, click `Create` to create the user. - -On success, you'll see a confirmation message in the top right corner. - -:::warning -If the user already exists, you will not be able to create an account for them. -::: - -##### Remove a user - -To remove a user from the device, click on the `X` icon next to their name. - -![](https://i.imgur.com/HBqlqN1.png) - -#### Device information - -Verbose information about the device, including: - - Overview: General device state information, and summarized device information over time. - - Timeline: A detailed timeline of data received from the device, and received by SIM providers. - - Config Pages: Current config pages applied to the device. - -![](https://i.imgur.com/GnwHbXd.png) - -##### Plan - -The top of the overview summarizes the current plan and billing state of the device. - -![](https://i.imgur.com/tIjgUsM.png) - -##### Metric Summary - -An expandable overview of some device metrics, errors, sends and power usage are then displayed. - -You can mouse over the graphs to see more details about the data. - -Use the `+1 Day` and `+1 Week` buttons to expands the time range of the graph into the past. - -![](https://i.imgur.com/alZiO0u.png) - -This data is then summarized further with some key metrics. - -- Total Time -- Total Points -- Avenge Signal -- Average Points per transmit -- Average Time Between Points -- Average Time Between -- Average Power per Transmit -- Average Power per Point -- Battery percent and voltage at start of the time range. -- Battery percent and voltage at end of the time range. -- Max battery voltage during the time range. - -And a breakdown of the source of locations received during the time range. - -![](https://i.imgur.com/oIgFTmS.png) - -##### Timeline - -The timeline shows a detailed view of events from and related to the device. - -This will poll for new events as they happen, so you should be able to see your device connecting and sending data when active. - -![](https://i.imgur.com/WoevCJG.png) - -:::warning -If your device has not recently sent any data, you might find the timeline empty, or timing out. -::: - -##### Config Pages - -The config pages tab shows the current config pages applied to the device. - -You can remove config pages by clicking the `X` icon next to the config page name. - -![](https://i.imgur.com/nrXrJW2.png) - -#### Manage Forwarding - -Forwarding is a new feature that allows you to forward data from your devices to other services, currently webhooks and MQTT. - -![](https://i.imgur.com/zkPvShs.png) - -This will replace similar messaging based on Notifications, which is only accessible via API or the [Cloud app](/apps/cloud/account/notifications). - -If you would like to use this feature, please contact support to get it enabled on your account, as it is not yet at General Availability. - -### Bulk actions - -You can select multiple devices and perform actions on them by using the check boxes at the left of each row. - -![](https://i.imgur.com/Y2LyH7r.png) - -#### Export - -Exporting selected devices will display a modal allowing you to copy a IDs, Serial numbers, IMEIs or ICCIDs in a bulk format. - -![](https://i.imgur.com/GiLWsY4.png) - -#### Settings - -Settings allows you to change the settings of multiple devices at once, making use of [config pages](./configs.html) that you have on your account. - -![](https://i.imgur.com/MTQGSiH.png) - - - -#### Users - -Allows, bulk adding or removing of users from the selected devices. - -![](https://i.imgur.com/KIweB1w.png) - -#### Tags - -Allows, bulk adding or removing of tags from the selected devices. - -Devices with no tags will allow you to add new tags. - -![](https://i.imgur.com/KjnS0iT.png) - -Changes can be reviewed before they are applied. - -![](https://i.imgur.com/lE4YthQ.png) - -If selected devices have a mixture of tags, they will be shown differently in the existing tags list. - -![](https://i.imgur.com/ES7HrLi.png) - -Tags can be: - - Removed from all devices, using the bin icon. - - Applied to all devices by clicking tags only applied to "Some devices" (in yellow). - -#### Activate / Deactivate - -Bulk activations and deactivations of devices. diff --git a/apps/admin/devices/bulk/activate.md b/apps/admin/devices/bulk/activate.md new file mode 100644 index 0000000..1414fac --- /dev/null +++ b/apps/admin/devices/bulk/activate.md @@ -0,0 +1,6 @@ +--- +outline: shallow +--- +# Activate / Deactivate (bulk) + +Bulk activations and deactivations of devices. diff --git a/apps/admin/devices/bulk/export.md b/apps/admin/devices/bulk/export.md new file mode 100644 index 0000000..aeaf515 --- /dev/null +++ b/apps/admin/devices/bulk/export.md @@ -0,0 +1,8 @@ +--- +outline: shallow +--- +# Export + +Exporting selected devices will display a modal allowing you to copy IDs, Serial numbers, IMEIs or ICCIDs in a bulk format. + +![](https://i.imgur.com/GiLWsY4.png) diff --git a/apps/admin/devices/bulk/index.md b/apps/admin/devices/bulk/index.md new file mode 100644 index 0000000..6d59e1a --- /dev/null +++ b/apps/admin/devices/bulk/index.md @@ -0,0 +1,9 @@ +--- +outline: deep +order: 50 +--- +# Bulk actions + +Bulk actions operate on multiple selected devices from the devices list. + +Some bulk actions can conflict across devices, and lead to error messages, so make sure to select only devices that can share the same action. diff --git a/apps/admin/devices/bulk/settings.md b/apps/admin/devices/bulk/settings.md new file mode 100644 index 0000000..6e67e8a --- /dev/null +++ b/apps/admin/devices/bulk/settings.md @@ -0,0 +1,10 @@ +--- +outline: shallow +--- +# Settings (bulk) + +Settings allows you to change the settings of multiple devices at once, making use of config pages that you have on your account. + +![](https://i.imgur.com/MTQGSiH.png) + + diff --git a/apps/admin/devices/bulk/tags.md b/apps/admin/devices/bulk/tags.md new file mode 100644 index 0000000..310ca74 --- /dev/null +++ b/apps/admin/devices/bulk/tags.md @@ -0,0 +1,22 @@ +--- +outline: shallow +--- +# Tags (bulk) + +Allows bulk adding or removing of tags from the selected devices. + +Devices with no tags will allow you to add new tags. + +![](https://i.imgur.com/KjnS0iT.png) + +Changes can be reviewed before they are applied. + +![](https://i.imgur.com/lE4YthQ.png) + +If selected devices have a mixture of tags, they will be shown differently in the existing tags list. + +![](https://i.imgur.com/ES7HrLi.png) + +Tags can be: + - Removed from all devices, using the bin icon. + - Applied to all devices by clicking tags only applied to "Some devices" (in yellow). diff --git a/apps/admin/devices/bulk/users.md b/apps/admin/devices/bulk/users.md new file mode 100644 index 0000000..fd6ba76 --- /dev/null +++ b/apps/admin/devices/bulk/users.md @@ -0,0 +1,8 @@ +--- +outline: shallow +--- +# Users (bulk) + +Allows bulk adding or removing of users from the selected devices. + +![](https://i.imgur.com/KIweB1w.png) diff --git a/apps/admin/devices/firmware.md b/apps/admin/devices/firmware.md new file mode 100644 index 0000000..a77e5bd --- /dev/null +++ b/apps/admin/devices/firmware.md @@ -0,0 +1,9 @@ +--- +outline: shallow +order: 3 +--- +# Schedule Firmware Update + +Clicking on the firmware version will open a dialog allowing you to schedule a firmware update for the device. + +![](https://i.imgur.com/sK66Th6.png) diff --git a/apps/admin/devices/forwarding.md b/apps/admin/devices/forwarding.md new file mode 100644 index 0000000..75f5613 --- /dev/null +++ b/apps/admin/devices/forwarding.md @@ -0,0 +1,13 @@ +--- +outline: shallow +order: 8 +--- +# Manage Forwarding + +Forwarding allows you to forward data from your devices to other services, currently webhooks and MQTT. + +![](https://i.imgur.com/zkPvShs.png) + +This will replace similar messaging based on Notifications, which is only accessible via API or the [Cloud app](/apps/cloud/account/notifications). + +If you would like to use this feature, please contact support to get it enabled on your account, as it is not yet at General Availability. diff --git a/apps/admin/devices/identifiers.md b/apps/admin/devices/identifiers.md new file mode 100644 index 0000000..894dc10 --- /dev/null +++ b/apps/admin/devices/identifiers.md @@ -0,0 +1,9 @@ +--- +outline: shallow +order: 1 +--- +# Reveal ICCID & IMEI + +Click the `(more)` link in the identifiers column to reveal the ICCID and IMEI of the device. + +![](https://i.imgur.com/xoTN8ga.png) diff --git a/apps/admin/devices/index.md b/apps/admin/devices/index.md new file mode 100644 index 0000000..8860f18 --- /dev/null +++ b/apps/admin/devices/index.md @@ -0,0 +1,44 @@ +--- +outline: deep +--- + +# Devices + +The devices page lists all devices that you have access to. + +From here you can view device status, location, and other information. You can also perform actions on devices, such as viewing logs, sending commands, and managing settings. + +A variety of individual and bulk actions are available. + +![Lightbug Admin device list](https://i.imgur.com/pHBzHGL.png) + +## Fields + +The device list shows the following fields: +- Identifiers: Static [identifiers](/terminology/devices#identity) for the device. + - ID + - Serial Number + - IMEI + - ICCID +- Names + - Name: User defined name for the device. + - Type: Device type, such as `ZeroN` etc. + - Tags: User defined [tags](/terminology/devices#tags) for the device. +- Seen + - Last: Time the device was last seen by the Lightbug platform, this may not be a 1:1 match with when data was last received. + - First: Time the device was fist seen by the Lightbug platform, likely around the time it was manufactured. +- Users +- Plan details +- Firmware +- Status + - Battery + - Enabled +- [Actions](#actions) + +## Filters + +Filters can be used to narrow down the list of devices. + +Such as all `ZeroN` devices. + +![](https://i.imgur.com/JkdXTz6.png) diff --git a/apps/admin/devices/information.md b/apps/admin/devices/information.md new file mode 100644 index 0000000..72622fa --- /dev/null +++ b/apps/admin/devices/information.md @@ -0,0 +1,65 @@ +--- +outline: deep +order: 7 +--- +# Device information + +Verbose information about the device, including: + - Overview: General device state information, and summarized device information over time. + - Timeline: A detailed timeline of data received from the device, and received by SIM providers. + - Config Pages: Current config pages applied to the device. + +![](https://i.imgur.com/GnwHbXd.png) + +## Plan + +The top of the overview summarizes the current plan and billing state of the device. + +![](https://i.imgur.com/tIjgUsM.png) + +## Metric Summary + +An expandable overview of some device metrics, errors, sends and power usage are then displayed. +You can mouse over the graphs to see more details about the data. + +Use the `+1 Day` and `+1 Week` buttons to expands the time range of the graph into the past. + +![](https://i.imgur.com/alZiO0u.png) + +This data is then summarized further with some key metrics. + +- Total Time +- Total Points +- Avenge Signal +- Average Points per transmit +- Average Time Between Points +- Average Time Between +- Average Power per Transmit +- Average Power per Point +- Battery percent and voltage at start of the time range. +- Battery percent and voltage at end of the time range. +- Max battery voltage during the time range. + +And a breakdown of the source of locations received during the time range. + +![](https://i.imgur.com/oIgFTmS.png) + +## Timeline + +The timeline shows a detailed view of events from and related to the device. + +This will poll for new events as they happen, so you should be able to see your device connecting and sending data when active. + +![](https://i.imgur.com/WoevCJG.png) + +:::warning +If your device has not recently sent any data, you might find the timeline empty, or timing out. +::: + +## Config Pages + +The config pages tab shows the current config pages applied to the device. + +You can remove config pages by clicking the `X` icon next to the config page name. + +![](https://i.imgur.com/nrXrJW2.png) diff --git a/apps/admin/devices/name.md b/apps/admin/devices/name.md new file mode 100644 index 0000000..f62c5f8 --- /dev/null +++ b/apps/admin/devices/name.md @@ -0,0 +1,11 @@ +--- +outline: shallow +order: 2 +--- +# Set device name + +Hovering over a device name will reveal a pencil icon, which can be clicked to edit the device name. + +Hit `Enter` to save the new name, or `Escape` to cancel. + +![](https://i.imgur.com/22CIjYw.png) diff --git a/apps/admin/devices/rtk.md b/apps/admin/devices/rtk.md new file mode 100644 index 0000000..849bc55 --- /dev/null +++ b/apps/admin/devices/rtk.md @@ -0,0 +1,48 @@ +--- +outline: shallow +order: 6 +title: RTK +--- +# Manage RTK + +RTK-specific controls are available for RTK-capable devices. + +Open the RTK dialog from the device row actions to view and modify RTK settings by clicking the . + +The settings can be used to configure both rover and base station modes. + +## General + +### Group + +Selected by the user. +Any number 0 - 250. + +All devices assigned the same group number will only connect to a Base unit with the same group number. +This prevents cross communication between groups. +This is useful when you have more than one group working close to each other. + +Each group will be connected to their own Base unit. +Ensure each group is labelled with the corresponding number. + +### NTRIP Settings + +Input these configuration settings as per the supplier and setup. + +This is compulsory for a high level of accuracy. + +## Base mode + +### Fixed Position + +If you have known GPS coordinates select Fixed Position to green and input Altitude, and, Latitude & Longitude coordinates. + +![](https://i.imgur.com/URMQxLP.png) + +### Survey + +Survey mode allows the base station to determine its own position. + +## Rover + +![](https://i.imgur.com/QP5Im8F.png) diff --git a/apps/admin/devices/settings.md b/apps/admin/devices/settings.md new file mode 100644 index 0000000..a0928e9 --- /dev/null +++ b/apps/admin/devices/settings.md @@ -0,0 +1,11 @@ +--- +outline: shallow +order: 5 +--- +# Manage Settings + +Settings allows you to change device settings. From the devices list you can open the settings dialog for a single device and apply config pages. + +See also: bulk settings page for applying settings to multiple devices. + +![](https://i.imgur.com/MTQGSiH.png) diff --git a/apps/admin/devices/users.md b/apps/admin/devices/users.md new file mode 100644 index 0000000..e35b01f --- /dev/null +++ b/apps/admin/devices/users.md @@ -0,0 +1,46 @@ +--- +outline: shallow +order: 4 +--- +# Manage Users + +Clicking on the manage users icon will open a dialog allowing you to add or remove users from the device. + +Users can have different global permissions, which can be controlled from the [users page](/apps/admin/users#permissions). + +![](https://i.imgur.com/yIbkNpT.png) + +## Add Existing user + +In order to select an existing user, click on their name from the list. + +![](https://i.imgur.com/5aFeQlp.png) + +On success, you'll see a confirmation message in the top right corner. + +:::warning +If the user already exists, and they are not a sub user of your account, you will not be able to select them. +If this is the case please contact support to get them added to your account. +::: + +## Add New user + +To create a new user, click on the `Create New` button. + +This will open a dialog allowing you to enter the new users details. + +![](https://i.imgur.com/QEnoQwF.png) + +Once you have entered the details, click `Create` to create the user. + +On success, you'll see a confirmation message in the top right corner. + +:::warning +If the user already exists, you will not be able to create an account for them. +::: + +## Remove a user + +To remove a user from the device, click on the `X` icon next to their name. + +![](https://i.imgur.com/HBqlqN1.png) diff --git a/apps/admin/permissions.md b/apps/admin/permissions.md index bfac484..31f24b5 100644 --- a/apps/admin/permissions.md +++ b/apps/admin/permissions.md @@ -6,7 +6,7 @@ Different permissions will reveal different interfaces in the side bar. | Page | user | trackerAdmin |Description | | -- | -- | -- | -- | -| [Devices](./devices.html) | ✅ | ✅ |List all devices on the account| +| [Devices](/apps/admin/devices/) | ✅ | ✅ |List all devices on the account| | [Configs](./configs.html) | |✅ |Manage `config pages` that can be applied to devices| | [Users](./users.html) | |✅ |Manage sub users of your account| | [Invoice Audit](./invoice-audit.html) | |✅ || diff --git a/apps/cloud/creating-account.md b/apps/cloud/creating-account.md index facada9..9a02bc7 100644 --- a/apps/cloud/creating-account.md +++ b/apps/cloud/creating-account.md @@ -10,14 +10,14 @@ First, [navigate to the login page](https://lightbug.cloud/#/auth/login). :::tabs == Desktop - +![](https://i.imgur.com/h3AUXJJ.png) == Mobile - +![](https://i.imgur.com/o9kao3O.png) ::: Click `SIGN UP`. - +![](https://i.imgur.com/8OL5n0e.png){.center} And the registration form will appear. @@ -25,9 +25,9 @@ Enter your details in the registration form. :::tabs == Desktop - +![](https://i.imgur.com/srFc6e8.png) == Mobile - +![](https://i.imgur.com/ECuZlD9.png) ::: And click `REGISTER`. @@ -44,9 +44,9 @@ It will guide you through the steps of adding your first device to your account. :::tabs == Desktop - +![](https://i.imgur.com/3iaxLSz.png) == Mobile - +![](https://i.imgur.com/omtoo0k.png) ::: Swipe the screen, or click the `NEXT` button to proceed through the onboarding process. @@ -55,9 +55,9 @@ The first screen tells you some useful initial information about a core device. :::tabs == Desktop - +![](https://i.imgur.com/FSWJ39v.png) == Mobile - +![](https://i.imgur.com/pyLGodN.png) ::: Swipe the screen, or click the `NEXT` button to proceed through the onboarding process. @@ -66,9 +66,9 @@ The second screen allows you to add your first device. :::tabs == Desktop - +![](https://i.imgur.com/X1CFB33.png) == Mobile - +![](https://i.imgur.com/funMDW2.png) ::: Enter the serial number of your device into the input field, and click `REGISTER`. @@ -81,9 +81,9 @@ You will then be asked to select a currency for your account, before you can cho :::tabs == Desktop - +![](https://i.imgur.com/ZNdAxeT.png) == Mobile - +![](https://i.imgur.com/JQbqZTl.png) ::: After selecting a currency, you can choose a plan for your device. @@ -92,33 +92,34 @@ You can find details of each plan, and also buy them in bulk via a [sales enquir :::tabs == Desktop - +![](https://i.imgur.com/wpopzKd.png) == Mobile - +![](https://i.imgur.com/ElW4Bok.png) ::: If your account already has purchased plans assigned to it, you'll be able to select one of those plans. They will be displayed in this list, showing how many months have been paid for. - + +![=450x](https://i.imgur.com/qSNZwZW.png){.center} After selecting a plan, if payment details are not yet attached to your account, you will be asked to enter them. :::tabs == Desktop - +![](https://i.imgur.com/LZku5SU.png) == Mobile - +![](https://i.imgur.com/H9Td6jM.png) ::: Successful payment and plan activation will take you to the last page of the onboarding process. :::tabs == Desktop - +![](https://i.imgur.com/byxRofc.png) == Mobile - +![](https://i.imgur.com/S8BKfUl.png) ::: Follow the instructions on the screen to complete the onboarding process and activate your device. @@ -129,31 +130,31 @@ Once a device has been added to the account, you'll be taken to the main interfa ### Device & Search - +![](https://i.imgur.com/B7g28C5.png) ### Device Information - +![](https://i.imgur.com/B33edbG.png) ### History List - +![](https://i.imgur.com/CmKEheK.png) ### Date selection - +![](https://i.imgur.com/nYaTX1q.png) ### Data & Playback - +![](https://i.imgur.com/K6FwXmo.png) ### Page select - +![](https://i.imgur.com/58mlwp9.png) ### Ready to go - +![](https://i.imgur.com/7WRMdfm.png) ## Map diff --git a/apps/cloud/map/controls.md b/apps/cloud/map/controls.md index b677007..7d99f45 100644 --- a/apps/cloud/map/controls.md +++ b/apps/cloud/map/controls.md @@ -8,7 +8,7 @@ outline: [1,3] To change the Map view settings, click on the layer icon in the top right corner. -![Map View Layer button](https://i.imgur.com/L49Owzb.png) +![Map View Layer button](https://i.imgur.com/L49Owzb.png){.center} This will open a panel where you can change the map view settings. @@ -26,7 +26,7 @@ The two sections allow choice of tile set and layers to be displayed. | Tile set| Description | | --- | --- | | Street | Mapbox provided OSM tiles | -| Satellite | Mapbox provided satellite tiles (maxar) | +| Satellite | Mapbox provided satellite tiles (Maxar) | | Hybrid | A combination of Street and Satellite tiles | | Traffic | Street tiles with traffic information | @@ -56,7 +56,7 @@ Devices are always shown on the map, but you can choose how they are displayed, | Clustered | Not Clustered | | --------------------------------------------- | ------------------------------------------------- | -| ![Clustered](https://i.imgur.com/N7tKJIC.png) | ![Not Clustered](https://i.imgur.com/oo3aNqQ.png) | +| ![Clustered](https://i.imgur.com/N7tKJIC.png){.center} | ![Not Clustered](https://i.imgur.com/oo3aNqQ.png){.center} | | Clusters show the number of devices within an area | Each device is shown individually on the map, [optionally with the name](/apps/cloud/account/preferences) | Clicking on a cluster will zoom in to show the individual devices, or smaller clusters. diff --git a/apps/cloud/map/device-list.md b/apps/cloud/map/device-list.md index a9cf023..653f311 100644 --- a/apps/cloud/map/device-list.md +++ b/apps/cloud/map/device-list.md @@ -8,15 +8,15 @@ The device list provides an overview of all the devices on your account. In order to see the device list, you need to expand the sidebar by using the arrow. -![](https://i.imgur.com/2umqTRF.png) +![](https://i.imgur.com/2umqTRF.png){.center} The List will expand, and you will see all the devices on your account that have been active in the last 90 days including various information about each device. :::tabs == Desktop - +![](https://i.imgur.com/bv8vapO.png) == Mobile - +![](https://i.imgur.com/Ei8Nqvk.png) ::: ::: warning @@ -42,14 +42,14 @@ Here are some examples of what the device rows can look like: | Image | Description | | --- | --- | -| | An active device, that has just transmitted data, and was charging on last transmit | -| | An active device, that transmitted data 3 minutes ago, and was charging on last transmit -| | An active device, that has not connected since 29 August 2024, and had very little battery on last transmitted | -| | A deactivated device, that last reported being on 72% battery | -| | A deactivated device, that last reported being on 74% battery, and in the "Bristol area" zone. | -| | A deactivated device, that last reported being on 100% battery, and in the "Bristol area" zone, and has a [tag](/apps/cloud/device-settings/tags.html) | -| | When using wired trackers, Battery % will not be shown, Powered status (ignition) will be shown | -| | An active device, that has just transmitted data, and is in battery saver mode at 13% | -| | A bluetooth beacon that has been added to the account | +| ![](https://i.imgur.com/6iKfpTu.png){.center} | An active device, that has just transmitted data, and was charging on last transmit | +| ![](https://i.imgur.com/yeynpZl.png){.center} | An active device, that transmitted data 3 minutes ago, and was charging on last transmit +| ![](https://i.imgur.com/0Ws7yNs.png){.center} | An active device, that has not connected since 29 August 2024, and had very little battery on last transmitted | +| ![](https://i.imgur.com/ZYZseSF.png){.center} | A deactivated device, that last reported being on 72% battery | +| ![](https://i.imgur.com/MrymS6o.png){.center} | A deactivated device, that last reported being on 74% battery, and in the "Bristol area" zone. | +| ![](https://i.imgur.com/KND4U7x.png){.center} | A deactivated device, that last reported being on 100% battery, and in the "Bristol area" zone, and has a [tag](/apps/cloud/device-settings/tags.html) | +| ![](https://i.imgur.com/eVBH9OQ.png){.center} | When using wired trackers, Battery % will not be shown, Powered status (ignition) will be shown | +| ![](https://i.imgur.com/MEhzqHR.png){.center} | An active device, that has just transmitted data, and is in battery saver mode at 13% | +| ![](https://i.imgur.com/u3glJ6q.png){.center} | A bluetooth beacon that has been added to the account | Clicking on a device row, will focus the map on that device, and open the device information panel. diff --git a/apps/cloud/map/device-view.md b/apps/cloud/map/device-view.md index 5453f4c..de06c95 100644 --- a/apps/cloud/map/device-view.md +++ b/apps/cloud/map/device-view.md @@ -6,16 +6,16 @@ The device view focuses in on a single device point, and shows detailed informat :::tabs == Desktop - +![](https://i.imgur.com/sIVl24t.png) == Mobile - +![](https://i.imgur.com/xJ3sqRC.png) ::: ## Details In the top left of the device view, you will see the device name, color, as well as information about the last transmission. -![](https://i.imgur.com/rSNOeNC.png) +![](https://i.imgur.com/rSNOeNC.png){.center} @@ -25,7 +25,7 @@ Clicking the dropdown will open the [History list](#history-list) for the device The time range that is currently being used is displayed at the bottom of the map. -![](https://i.imgur.com/5BTlmMJ.png) +![](https://i.imgur.com/5BTlmMJ.png){.center} By default, the map view time range selection is set to midnight yesterday, to the current time today. @@ -35,9 +35,9 @@ Clicking on the time range selector will open a panel where you can change the t :::tabs == Desktop - +![](https://i.imgur.com/NMijD9C.png) == Mobile - +![](https://i.imgur.com/ku85nHB.png) ::: The time range selector allows you to choose a custom time range, or one of the predefined options. @@ -52,13 +52,13 @@ The time range selector can only be used to show at most 90 days of data at once Next to the time range selector, you will see a playback button. -![](https://i.imgur.com/5BTlmMJ.png) +![](https://i.imgur.com/5BTlmMJ.png){.center} Clicking this will open the playback panel at the bottom of the page. Mousing over the graph will displays data names and values. -![](https://i.imgur.com/EEb61bj.png) +![](https://i.imgur.com/EEb61bj.png){.center} :::tip This is best viewed on a desktop, as the playback panel is quite large. @@ -72,7 +72,7 @@ Within the selected time range, you can use the playback controls (direction key You can also choose to drag the playback slider to a specific point in time. -![](https://i.imgur.com/yzEEsvE.png) +![](https://i.imgur.com/yzEEsvE.png){.center} ### Options {#data-playback-options} @@ -98,9 +98,9 @@ The history list can be accessed by clicking the dropdown in the top left of the :::tabs == Desktop - +![](https://i.imgur.com/vjZFWL4.png) == Mobile - +![](https://i.imgur.com/vnZ9r0p.png) ::: The list shows all the locations transmitted by the in the given [time range](#time-range). @@ -126,7 +126,7 @@ General control Some dots represent device seen. The number on each of the dot represents the number of devices seen throughout the time frame. - Blue: BLE Devices (Paired or unpaired) -- Orange: Other nearby Lightbugs +- Orange: Other nearby Lightbug devices Any events that have occurred will be shown on the map as a dot. diff --git a/components/DeviceSpecTable.vue b/components/DeviceSpecTable.vue index 07e8819..4cd65a2 100644 --- a/components/DeviceSpecTable.vue +++ b/components/DeviceSpecTable.vue @@ -8,15 +8,17 @@ - -

Overview

+ + + +

Overview

{{ specs.product.description }} - +
- +
{{ key }}{{ value }}
@@ -48,12 +50,28 @@ import { ref, watchEffect } from 'vue' import yaml from 'js-yaml' import DownloadPdfButton from './DownloadPdfButton.vue' +import DownloadYamlButton from './DownloadYamlButton.vue' +import DownloadBookletButton from './DownloadBookletButton.vue' const props = defineProps({ yamlText: { type: String, required: true } + , + // Optional override for the device title. If provided, this will be used + // instead of the title extracted from the YAML. + deviceTitle: { + type: String, + required: false + } + , + // Optional mapping from term -> url. Allows overriding where terms link to. + termLinkMap: { + type: Object, + required: false, + default: () => ({}) + } }) const specs = ref(null) @@ -61,8 +79,8 @@ const displaySpecs = ref({}) const deviceTitle = ref('Device Specification') const genericSections = ref([]) -// An allowed list of keys to use from the YAML for now.. -const sectionKeys = ['physical','integrations','connectivity','battery','positioning','sensors','charging','user interface','components'] +// An allowed list of keys to use from the YAML for now.. (and order) +const sectionKeys = ['physical','integrations','user interface','connectivity','positioning','sensors','battery','charging','components'] function normalizePhrase(str) { if (!str) return '' @@ -76,6 +94,33 @@ function normalizePhrase(str) { return phrase } +const defaultTermLinkMap = { + rtk: '/terminology/positioning/rtk', + gnss: '/terminology/positioning/gnss', + "Wi-Fi AP scanning": '/terminology/positioning/wifi', +} + +function linkTerms(text) { + if (!text || typeof text !== 'string') return text + const map = { ...defaultTermLinkMap, ...props.termLinkMap } + // Sort keys by length desc to avoid partial matches (e.g., 'gps' inside other words) + const keys = Object.keys(map).sort((a, b) => b.length - a.length) + let out = text + for (const key of keys) { + const url = map[key] + const re = new RegExp('\\b' + key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\$&') + '\\b', 'gi') + out = out.replace(re, match => `${match}`) + } + return out +} + +function linkUrls(text) { + if (!text || typeof text !== 'string') return text + // Simple URL regex (http/https). Keep it conservative. + const urlRe = /https?:\/\/[^\s"'<>]+/g + return text.replace(urlRe, url => `${url}`) +} + function formatValueForDisplay(val) { if (Array.isArray(val)) { // Array: join items, format each recursively @@ -97,15 +142,20 @@ watchEffect(() => { genericSections.value = [] if (specs.value && specs.value.product) { const p = specs.value.product - deviceTitle.value = p.sku ? `${p.name} (${p.sku})` : p.name + // Prefer the explicit prop if provided, otherwise derive from YAML + if (props.deviceTitle) { + deviceTitle.value = props.deviceTitle + } else { + deviceTitle.value = p.sku ? `${p.name} (${p.sku})` : p.name + } // Main table (excluding sectionKeys) displaySpecs.value = { - 'Name': p.name, + 'Name': linkUrls(linkTerms(p.name)), 'Version': p.version, 'Serial prefix': p.prefix, - 'Connectivity': p.connectivity ? Object.keys(p.connectivity).join(', ') : '', - 'Positioning': p.positioning ? Object.keys(p.positioning).join(', ') : '', - 'Sensors': p.sensors ? Object.keys(p.sensors).join(', ') : '', + 'Connectivity': p.connectivity ? linkUrls(linkTerms(Object.keys(p.connectivity).join(', '))) : '', + 'Positioning': p.positioning ? linkUrls(linkTerms(Object.keys(p.positioning).join(', '))) : '', + 'Sensors': p.sensors ? linkUrls(linkTerms(Object.keys(p.sensors).join(', '))) : '', } // Generic section rendering for (const sectionKey of sectionKeys) { @@ -162,6 +212,10 @@ watchEffect(() => { .join('
') } displayValue = formatValueForDisplay(v) + if (typeof displayValue === 'string') { + displayValue = linkTerms(displayValue) + displayValue = linkUrls(displayValue) + } if (displayValue !== undefined && displayValue !== null && displayValue !== '' && displayValue !== '[]' && displayValue !== '{}') { rows.push({ label: normalizePhrase(k), value: displayValue }) } diff --git a/components/DownloadBookletButton.vue b/components/DownloadBookletButton.vue new file mode 100644 index 0000000..dc1b4d4 --- /dev/null +++ b/components/DownloadBookletButton.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/components/DownloadPdfButton.vue b/components/DownloadPdfButton.vue index 800d30b..436a263 100644 --- a/components/DownloadPdfButton.vue +++ b/components/DownloadPdfButton.vue @@ -1,11 +1,11 @@ + + diff --git a/components/GenerateConsts.vue b/components/GenerateConsts.vue index 4f2888e..998185f 100644 --- a/components/GenerateConsts.vue +++ b/components/GenerateConsts.vue @@ -96,7 +96,6 @@ - -# Headers - -These header field types are reserved across all message types. - - - -## 1: Message ID - -Used to identify the message. - -Can be one of uint8, uint16, uint32, or uint64, as Little Endian. - -Should be used with ACK messages to identify the message that is being ACKed. - -ACKs should return the same message ID and type as the message being ACKed. - -## 2: Client ID - -Used to identify the client that sent the message where appropriate. - -## 3: Response Message ID - -This message is responding to a previous message with the specified message ID. - -Should be the same message ID and type as the message being responded to. - -## 4: Message Status - -The status of the response. - -Values below 0 indicate an OK status, but with special meanings. - -Values above 0 indicate an error or status that is not OK. - -| Value | Status Description | -|--------|----------------------------------------------------| -| 0 | OK | -| -1 | OK Processing (there will be one or more further responses) | -| -126 | OK No Ack (internal only, message does not require an ACK) | -| -127 | OK Already Responded (message has already been responded to) | -| 1 | NOT OK (Generic error) | -| 3 | Method not supported | -| 4 | Invalid payload param | -| 5 | Invalid state | -| 6 | No data | -| 7 | Not supported | -| 8 | Failed, will retry | -| 9 | Failed permanently | -| 10 | Unknown message | - -## 5: Method - -- 1: Set, Request a change, using the data provided. -- 2: Get, Request the current value or values. -- 3: Subscribe, Request to be notified with updates for the message. -- 4: Do, Perform an action, using the data provided. -- 5: Unsubscribe, Request to no longer be notified with updates for the message. - -## 6: Subscription interval - -Interval in ms. To be used with the SUBSCRIBE method - - - -## 10: Forwarded For - -ID of the client sending the original message that is being forwarded. - -## 11: Forwarded RSSI - -RSSI of forwarded message, where applicable. - -## 12: Forwarded SNR - -SNR of forwarded message, where applicable. - - - -## 14: Forward To - -ID of the client to forward the message to. Forwarding to type alters the meaning of this field diff --git a/devices/api/index.md b/devices/api/index.md index 204dffc..7a8e458 100644 --- a/devices/api/index.md +++ b/devices/api/index.md @@ -8,38 +8,34 @@ import ProtocolBytes from '../../components/ProtocolBytes.vue'; # Device API -The device API makes use of the Lightbug communication protocol, also known as the V3 protocol, which is a byte oriented protocol used for device communication. +The device API is a messaging system for communicating with Lightbug devices. It allows you to send and receive [messages](/devices/api/messages/) to and from the device, enabling control and data exchange. -The protocol builds on top of existing Lightbug protocols, and is designed to be: - - Easy to use and understand - - Efficient to read and build - - Lightweight to store and transmit - - Usable in a variety of settings, without complex or bloated dependencies +It makes use of the [Lightbug communication protocol](/devices/api/protocol/), which is a byte oriented protocol used for device communication. -## API Access +This documentation focuses on the higher level element of this API first, including the [Toit SDK](/devices/api/sdks/toit/), before working its was down to the [message level](/devices/api/messages/), and finally the [protocol level](/devices/api/protocol/) which underpins it all. -API access depends on the device and may not be supported on all models. +You can [get started with Toit quickly](/devices/api/sdks/toit/), using an SDK built on top of the messages as another layer of abstraction. -Typically, it can be accessed via UART, I2C, or a UDP network connection. +## Capabilities + +The Device API allows you to: + - send commands to the device + - ask for data (GET) + - subscribe to data streams (SUBSCRIBE) + - receive responses, instructions and other data from the device -For access details, please [contact our support team](https://lightbug.io/contact/). +On the wire, a single message might look like `4c 42 03 0b 00 01 00 00 00 00 00 4b be`, however, the API abstracts this away so you can work with high level messaging concepts. -Or you can [get started with Toit quickly](/devices/api/sdks/toit/) using the Lightbug provided SDK. +## Accessability + +Typically, it can be accessed via UART, I2C, or a UDP network connection. -## Example Message +## Availability -An example [prefixed](structure#prefix) and minimal message might look as follows: +Device API access depends on the device and may not be supported on all models. -| Format | Message | -| ------ | --- | -| Bytes | 76 66 3 11 0 1 0 0 0 0 0 75 190 | -| Hex | `4c 42 03 0b 00 01 00 00 00 00 00 4b be` | +The [RH2 RTK device](/devices/rtk/) will be the first general release product to support the API, with a future low cost development board planned. - +For details, please [contact our support team](https://lightbug.io/contact/). -::: info -All integers are in [little-endian](https://en.wikipedia.org/wiki/Endianness) format eg. (uint16 `1` is represented as `0x01 0x00`). -::: +If you have a supported device, you can [get started with Toit quickly](/devices/api/sdks/toit/) using the Lightbug SDK, or communicate with the device from other languages using the messages documented here. diff --git a/devices/api/messages/10008-preset-page.md b/devices/api/messages/10008-preset-page.md index dfcebbc..59ff6e0 100644 --- a/devices/api/messages/10008-preset-page.md +++ b/devices/api/messages/10008-preset-page.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -47,4 +48,4 @@ byteString="3 14 0 24 39 1 0 1 1 126 0 0 25 55" ## Code - + diff --git a/devices/api/messages/10009-text-page.md b/devices/api/messages/10009-text-page.md index 79a16ed..f7e4330 100644 --- a/devices/api/messages/10009-text-page.md +++ b/devices/api/messages/10009-text-page.md @@ -6,8 +6,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -61,6 +62,7 @@ line3="Third" byteString="3 61 0 25 39 1 0 1 1 233 5 0 3 4 100 101 102 1 200 10 80 97 103 101 32 84 105 116 108 101 10 70 105 114 115 116 32 76 105 110 101 11 83 101 99 111 110 100 32 76 105 110 101 5 84 104 105 114 100 106 149" :boldPositions="[3,20,31,42,54]" :allowCollapse="true" defaultCollapsed="true" + :yaml-data="protocolData" /> Add a 4th line to the same page ID `200`, with the text `4th`, by providing the same page ID, and only the new text field. @@ -77,6 +79,7 @@ line4="4th" byteString="3 22 0 25 39 1 0 1 1 200 2 0 3 103 1 200 3 52 116 104 245 201" :boldPositions="[3,9,17]" :allowCollapse="true" defaultCollapsed="true" + :yaml-data="protocolData" /> Only a partial redraw will be performed in order to add the new line, and the existing lines will remain on the screen. @@ -85,4 +88,4 @@ Only a partial redraw will be performed in order to add the new line, and the ex For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/10010-menu-page.md b/devices/api/messages/10010-menu-page.md index 27681c0..e82cc05 100644 --- a/devices/api/messages/10010-menu-page.md +++ b/devices/api/messages/10010-menu-page.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -60,4 +61,4 @@ byteString="3 26 0 26 39 1 0 1 1 187 3 0 3 2 102 1 102 1 3 4 111 112 116 51 203 For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/10011-draw-bitmap.md b/devices/api/messages/10011-draw-bitmap.md index 9854101..9e59cc0 100644 --- a/devices/api/messages/10011-draw-bitmap.md +++ b/devices/api/messages/10011-draw-bitmap.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -24,7 +25,7 @@ These pages can be seen as a view of what is to come later this year. @@ -47,4 +49,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/1004-lora.md b/devices/api/messages/1004-lora.md index 0eeb75e..a8a1a84 100644 --- a/devices/api/messages/1004-lora.md +++ b/devices/api/messages/1004-lora.md @@ -5,9 +5,10 @@ outline: false @@ -21,10 +22,10 @@ These pages can be seen as a view of what is to come later this year. Used to interact with LORA on the device. - + ## Code For convenience, the following constants can be referring to this message type. - + diff --git a/devices/api/messages/11-open.md b/devices/api/messages/11-open.md index 5b6c739..6f139a3 100644 --- a/devices/api/messages/11-open.md +++ b/devices/api/messages/11-open.md @@ -4,11 +4,11 @@ outline: false --- ::: danger ⚠️ Not yet public @@ -19,16 +19,14 @@ These pages can be seen as a view of what is to come later this year. # 11: Open -Used to explicitly initiate communication. +{{yaml:public/files/protocol-v3.yaml:messages.11.description}} -Responses can be used to determine your target is alive and ready. +## Fields -Targets **MAY** require an open message to be sent before they will respond to other messages. - -Communications to Lightbug devices **MUST** start with an open message. + ## Code For convenience, the following constants can be referring to this message type. - + diff --git a/devices/api/messages/12-close.md b/devices/api/messages/12-close.md index 0baabb9..4259191 100644 --- a/devices/api/messages/12-close.md +++ b/devices/api/messages/12-close.md @@ -9,6 +9,7 @@ import SplitColumnView from '../../../components/SplitColumnView.vue'; import GenerateConsts from '../../../components/GenerateConsts.vue' import PayloadTable from '../../../components/PayloadTable.vue' import HeaderTable from '../../../components/HeaderTable.vue' +import { data as protocolData } from '../../../yaml-data.data.ts' ::: danger ⚠️ Not yet public @@ -25,4 +26,4 @@ Used to explicitly close communication. For convenience, the following constants can be referring to this message type. - + diff --git a/devices/api/messages/13-heartbeat.md b/devices/api/messages/13-heartbeat.md index 6e588a7..d32d6fe 100644 --- a/devices/api/messages/13-heartbeat.md +++ b/devices/api/messages/13-heartbeat.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -30,7 +31,7 @@ Devices currently default to sending a heartbeat every 15 seconds. @@ -43,10 +44,11 @@ Basic heartbeat message. byteString="3 15 0 13 0 1 0 1 2 55 2 0 0 41 1" :boldPositions="[3]" :allowCollapse="true" defaultCollapsed="true" + :yaml-data="protocolData" /> ## Code For convenience, the following constants can be referring to this message type. - + diff --git a/devices/api/messages/14-config.md b/devices/api/messages/14-config.md index dce04a4..8096c2c 100644 --- a/devices/api/messages/14-config.md +++ b/devices/api/messages/14-config.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -26,7 +27,7 @@ TODO... @@ -35,4 +36,4 @@ TODO... For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/15-position.md b/devices/api/messages/15-position.md index e59844d..8538e04 100644 --- a/devices/api/messages/15-position.md +++ b/devices/api/messages/15-position.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -26,7 +27,7 @@ These pages can be seen as a view of what is to come later this year. Used to interact with the devices position. - + @@ -64,4 +65,4 @@ byteString="3 20 0 30 0 3 0 3 4 1 1 131 1 1 1 92 0 0 84 149" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/31-gsm-control.md b/devices/api/messages/31-gsm-control.md index a29997a..a54906f 100644 --- a/devices/api/messages/31-gsm-control.md +++ b/devices/api/messages/31-gsm-control.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -26,7 +27,7 @@ These pages can be seen as a view of what is to come later this year. @@ -35,4 +36,4 @@ These pages can be seen as a view of what is to come later this year. For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/32-gsm-request-ownership.md b/devices/api/messages/32-gsm-request-ownership.md index a0a6121..cf6fbc9 100644 --- a/devices/api/messages/32-gsm-request-ownership.md +++ b/devices/api/messages/32-gsm-request-ownership.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -24,7 +25,7 @@ These pages can be seen as a view of what is to come later this year. @@ -33,4 +34,4 @@ These pages can be seen as a view of what is to come later this year. For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/34-device-status.md b/devices/api/messages/34-device-status.md index 606094d..fd849a7 100644 --- a/devices/api/messages/34-device-status.md +++ b/devices/api/messages/34-device-status.md @@ -8,6 +8,7 @@ import ProtocolBytes from '../../../components/ProtocolBytes.vue'; import SplitColumnView from '../../../components/SplitColumnView.vue'; import GenerateConsts from '../../../components/GenerateConsts.vue' import PayloadTable from '../../../components/PayloadTable.vue' +import { data as protocolData } from '../../../yaml-data.data.ts' ::: danger ⚠️ Not yet public @@ -25,7 +26,7 @@ Used to GET the general status of the device. ### Payload - + @@ -70,4 +73,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/38-button-press.md b/devices/api/messages/38-button-press.md index ae44f4e..7d23ff1 100644 --- a/devices/api/messages/38-button-press.md +++ b/devices/api/messages/38-button-press.md @@ -7,6 +7,7 @@ outline: false import ProtocolBytes from '../../../components/ProtocolBytes.vue'; import SplitColumnView from '../../../components/SplitColumnView.vue'; import GenerateConsts from '../../../components/GenerateConsts.vue' +import { data as protocolData } from '../../../yaml-data.data.ts' ::: danger ⚠️ Not yet public @@ -38,6 +39,7 @@ These pages can be seen as a view of what is to come later this year. byteString="0" :boldPositions="[3,12,15,16]" :allowCollapse="false" +:yaml-data="protocolData" /> @@ -47,4 +49,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/39-gps-control.md b/devices/api/messages/39-gps-control.md index 100738a..3707777 100644 --- a/devices/api/messages/39-gps-control.md +++ b/devices/api/messages/39-gps-control.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -28,7 +29,7 @@ Currently only accessible from Viper devices. @@ -48,4 +49,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/40-haptics-control.md b/devices/api/messages/40-haptics-control.md index 9eed036..542fc87 100644 --- a/devices/api/messages/40-haptics-control.md +++ b/devices/api/messages/40-haptics-control.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -42,6 +43,7 @@ If the request could not be fulfilled, the response status would be 2 (NOT OK), byteString="0" :boldPositions="[3,12,15,16]" :allowCollapse="false" +:yaml-data="protocolData" /> @@ -51,4 +53,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/41-temperature.md b/devices/api/messages/41-temperature.md index 392c83d..c5c035c 100644 --- a/devices/api/messages/41-temperature.md +++ b/devices/api/messages/41-temperature.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -29,8 +30,8 @@ These pages can be seen as a view of what is to come later this year. | Field | Name | Description | Type | Example | Actual | | ----- | ---------- | -------------------------------- | ------ | ------- | - | -If the request could not be fulfilled, the response status would be 2 (NOT OK), all header fields would also be returned, but the payload should not be expected. + :yaml-data="protocolData" @@ -49,4 +51,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/42-buzzer-control.md b/devices/api/messages/42-buzzer-control.md index da0a653..4138f98 100644 --- a/devices/api/messages/42-buzzer-control.md +++ b/devices/api/messages/42-buzzer-control.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -51,4 +52,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/43-battery-status.md b/devices/api/messages/43-battery-status.md index e968186..fb31fef 100644 --- a/devices/api/messages/43-battery-status.md +++ b/devices/api/messages/43-battery-status.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -60,4 +61,4 @@ byteString="3 32 0 43 0 2 0 3 1 4 99 0 0 0 4 36 0 0 0 2 0 2 1 1 100 4 223 79 141 For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/44-pressure.md b/devices/api/messages/44-pressure.md index 2f51236..0e86be0 100644 --- a/devices/api/messages/44-pressure.md +++ b/devices/api/messages/44-pressure.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -28,7 +29,8 @@ These pages can be seen as a view of what is to come later this year. | Field | Name | Description | Type | Example | Actual | | ----- | ---------- | -------------------------------- | ------ | ------- | - | - +:allowCollapse="false" +:yaml-data="protocolData" If the request could not be fulfilled, the response status would be 2 (NOT OK), all header fields would also be returned, but the payload should not be expected. @@ -40,6 +42,7 @@ If the request could not be fulfilled, the response status would be 2 (NOT OK), byteString="0" :boldPositions="[3,12,15,16]" :allowCollapse="false" + :yaml-data="protocolData" /> @@ -49,4 +52,4 @@ byteString="0" For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/45-alarm.md b/devices/api/messages/45-alarm.md index b88caae..ef54506 100644 --- a/devices/api/messages/45-alarm.md +++ b/devices/api/messages/45-alarm.md @@ -5,8 +5,9 @@ outline: false ::: danger ⚠️ Not yet public @@ -38,4 +39,4 @@ TODO. For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/47-cpu2-sleep.md b/devices/api/messages/47-cpu2-sleep.md index e35bc42..e865309 100644 --- a/devices/api/messages/47-cpu2-sleep.md +++ b/devices/api/messages/47-cpu2-sleep.md @@ -8,6 +8,7 @@ import ProtocolBytes from '../../../components/ProtocolBytes.vue'; import SplitColumnView from '../../../components/SplitColumnView.vue'; import GenerateConsts from '../../../components/GenerateConsts.vue'; import PayloadTable from '../../../components/PayloadTable.vue'; +import { data as protocolData } from '../../../yaml-data.data.ts' ::: danger ⚠️ Not yet public @@ -24,7 +25,7 @@ These pages can be seen as a view of what is to come later this year. @@ -41,4 +42,4 @@ TODO For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/51-link-data.md b/devices/api/messages/51-link-data.md index f1b6617..c37449f 100644 --- a/devices/api/messages/51-link-data.md +++ b/devices/api/messages/51-link-data.md @@ -5,9 +5,10 @@ outline: false ::: danger ⚠️ Not yet public @@ -26,7 +27,7 @@ Used to send data over a link. @@ -39,4 +40,4 @@ TODO For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/53-ublox-protection-level.md b/devices/api/messages/53-ublox-protection-level.md index 63fb02e..b880734 100644 --- a/devices/api/messages/53-ublox-protection-level.md +++ b/devices/api/messages/53-ublox-protection-level.md @@ -8,6 +8,7 @@ import ProtocolBytes from '../../../components/ProtocolBytes.vue'; import SplitColumnView from '../../../components/SplitColumnView.vue'; import GenerateConsts from '../../../components/GenerateConsts.vue' import PayloadTable from '../../../components/PayloadTable.vue' +import { data as protocolData } from '../../../yaml-data.data.ts' ::: danger ⚠️ Not yet public @@ -26,7 +27,7 @@ Used to retrieve [ublox protection level](https://www.u-blox.com/en/technologies @@ -39,4 +40,4 @@ TODO For convenience, the following constants can be used to reference the payload fields. - + diff --git a/devices/api/messages/index.md b/devices/api/messages/index.md index adec2f4..9205f6d 100644 --- a/devices/api/messages/index.md +++ b/devices/api/messages/index.md @@ -5,30 +5,58 @@ import ProtocolBytes from '../../../components/ProtocolBytes.vue' # Messages -Messages often make use of a few common [header fields](/devices/api/headers), and you can expect to see these in most messages types: +Messages are the core building blocks of the protocol, allowing you to send and receive data and commands to and from devices. -## Requests +All messages follow a common structure, but each type of message has its own specific purpose, payload, requirements and usage. -Requests may or may not require a [MH 5: Method](./../headers#_5-method) header field, such as `GET`, `DO`, `SET` or `SUBSCRIBE`. +## Types -This is decided by the individual message type, and if required, should be included in the header. +Messages all have a type, represented as a `uint16` value, which defines the structure and purpose of the message, including what headers and payload it may or should contain. +Some example message types for the device API include: +- [13: Heartbeat](./13-heartbeat) - A simple message to indicate the communication link is alive +- [34: Device Status](./34-device-status) - A message containing various status information about the device +- [10011: Draw Element](./10011-draw-bitmap) - A message to draw a shape on the device's display +- ... +You can find complete documentation for the messages used as part of the device API in the sidebar of this page. -## Responses +Values of `60,000` to `61,000` are currently reserved for custom use. Feel free to implement your own messages within this range. -You should receive a response to every valid and expected message when the recipient is able to process the request. +## Header fields -When a message ID is provided in the request, any direct response should include the initiating message ID in the header [MH 3: Response Message ID](./../headers#_3-response-message-id). +Messages make use of a few common [header fields](/devices/api/protocol/headers) that are defined at the protocol level that you'll likely want to familiarize yourself with as they are used in device messaging. -Responses can come in the form of a basic [MT 5: ACK](./5-ack) or as the same message type as the request. +Such as: +- [1: Message ID](../protocol/headers#_1-message-id) for uniquely identifying messages +- [3: Response to](../protocol/headers#_3-response-to) for linking responses to requests +- [4: Status](../protocol/headers#_4-status) for indicating the status of a message +- [5: Method](../protocol/headers#_5-method) for optionally specifying the action to be taken -Responses should contain a [MH 4: Response Status](./../headers#_4-response-status) in the header, where 0 and below are various OK responses, and anything higher than 0 indicates a warning or error. +You can find the full list of header fields in the [Headers documentation](/devices/api/protocol/headers) for the protocol. -## Types +### Methods + +A method is an optional header field that can be included in messages, and is sometimes used throughout the device API. + +Currently defined methods are: +- `1: SET` - Set a value or state on the device +- `2: GET` - Get a value or state from the device +- `3: SUBSCRIBE` - Subscribe to updates for a value or state on the device +- `5: UNSUBSCRIBE` - Unsubscribe from updates for a value or state on the device -Per the specification, message types are represented by a single `uint16` value. +You can find more information about these methods in the [MH 5: Method](../protocol/headers#_5-method) section. -Values of `60,000` to `61,000` are currently reserved for custom use. +## Communication patterns + +You should receive a response to every valid and expected message when the recipient is able to process the request. + +When your message includes a [MH 1: Message ID](../protocol/headers#_1-message-id), the response should include the same message ID in the [MH 3: Response to](../protocol/headers#_3-response-to) header field. + +:::warning +If you do not include a message ID, you may not receive a response +::: + +Responses can come in the form of a basic [MT 5: ACK](./5-ack) or as the same message type as the request. -Feel free to implement your own messages within this range. +Responses can contain a [MH 4: Response Status](../protocol/headers#_4-message-status) in the header, where 0 and below are various OK responses, and anything higher than 0 indicates a warning or error. diff --git a/devices/api/protocol/examples.md b/devices/api/protocol/examples.md new file mode 100644 index 0000000..174b549 --- /dev/null +++ b/devices/api/protocol/examples.md @@ -0,0 +1,46 @@ +--- +outline: [2,3] +--- + + + +# Examples + +### Type 3, header empty, data empty + + + +### .. as above, with LB prefix bytes: + + + +### Type 6, header (1:1), data empty + + + +### Type 6, header (1:9), data empty + + + +### Type 10009, header empty, data (10:hello): + + diff --git a/devices/api/protocol/headers.md b/devices/api/protocol/headers.md new file mode 100644 index 0000000..d8b01b8 --- /dev/null +++ b/devices/api/protocol/headers.md @@ -0,0 +1,131 @@ +--- +outline: [1,3] +--- + + + +# Headers + +These header field types are reserved across all message types and usages of the protocol. + +For use in code, you can find a code generation section at the [bottom of this page](#code-generation). + +## 1: Message ID + +A `uint32` identifier for the message. + +Useful for debugging, tracing, deduplication, acking, re-sends, responses and subscriptions. + +## 2: Client ID + +A `uint32` or `uint64` identifier for the client sending the message. + +Can vary depending on the context of the messaging. + +## 3: Response to + +`uint32` message ID that this message is a response to. + +Can be used both for direct responses, or subscription updates. + +## 4: Message Status + +`uint8` + +The status of the message. + +If omitted, the message is assumed to be OK, or determined by the context of the message. + +0 indicates an OK status, below 0 is OK but with a special meaning. + +Values above 0 indicate an error or other status that is not OK. +| Value | Name | Description | +|-------|------|-------------| +| 0 | OK | Everything appears to be OK | +| 1 | Generic Error | | +| 2 | Missing Payload Parameter | | +| 3 | Method Not Supported | e.g., SETting GPS position | +| 4 | Invalid Payload Parameter | Unsupported values requested (e.g., requesting the GPS data at 100hz) | +| 5 | Invalid State | e.g., requesting GPS data stream before turning GPS on | +| 6 | No Data | e.g., requesting GPS or time data when not yet available | +| 7 | Not Supported | If the receiver does not support the requested action or method | +| 8 | Failed Will Retry | Currently only used for tx now | +| 9 | Failed Permanently | | +| 10 | Abandoned | Status code when an action has timed out or been deliberately cancelled by another process | +| 11 | Expired | Status code when a request has expired and has been cancelled, typically subscriptions | + +## 5: Method + +`uint8` + +The method of the message. + +| Value | Name | Description | +|-------|------|-------------| +| 1 | SET | Set one or more values that are provided in the message payload. | +| 2 | GET | Get one or more values that have their types provided in the message payload. If no payload types are provided, all available values are returned. | +| 3 | SUBSCRIBE | Subscribe to a value or values. If no payload types are provided, all available values will be subscribed to. If a value changes, the service will send a message with the new value. | +| 5 | UNSUBSCRIBE | Unsubscribe from some previously subscribed-to data. | + +## 6: Interval + +`uint32` + +Interval in ms. To be used with the SUBSCRIBE method + +## 7: Duration + +`uint32` + +Time in ms. For subscriptions this defines a duration to keep the subscription active for. 0 = no time limit. + +An ACK with EXPIRED status code will be sent if the subscription duration elapses without being renewed (with a new subscription request). + +For actions that can be timed, this defines how long the action should go on for. + +## 8: Timeout + +`uint32` + +Timeout in ms. When requesting data or services that can take time to acquire (such as a GPS fix), timeout defines how long to try for before abandoning the action. + +An ACK with ABANDONED status code will be sent in this case. + +For actions that support it, timeout defines how long to wait before performing the action. + +## 9: Forwarded For Type + +Reserved for future use. + +## 10: Forwarded For + +ID of the client sending the original message that is being forwarded. + +## 11: Forwarded RSSI + +RSSI of forwarded message, where applicable. + +## 12: Forwarded SNR + +SNR of forwarded message, where applicable. + +## 13: Forward To Type + +## 14: Forward To + +ID of the client to forward the message to. Forwarding to type alters the meaning of this field + +## 15: Storage Level + +Reserved for future use. + +## 16: Message Level + +Reserved for future use. + +## Code generation + + diff --git a/devices/api/protocol/index.md b/devices/api/protocol/index.md new file mode 100644 index 0000000..acfcc5e --- /dev/null +++ b/devices/api/protocol/index.md @@ -0,0 +1,83 @@ +--- +outline: [1,3] +--- + + + +# Protocol + +The protocol is designed to be: + - Easy to use and understand + - Efficient to read and build + - Lightweight to store and transmit + - Usable in a variety of settings, without complex or bloated dependencies + + +## Byte Breakdown + +In a byte stream, you may receive a series of messages. + +The makeup of a message is as follows (including options prefix) is as follows: + +``` +[optional prefix] + + ::= + + + ::= + ::= + + ::= +``` + +::: info +All integers are in [little-endian](https://en.wikipedia.org/wiki/Endianness) format eg. (uint16 `1` is represented as `0x01 0x00`). +::: + +As an example empty message including prefix (with no additional header or payload data): + + + +## Example Message + +An example [prefixed](structure#prefix) and minimal message might look as follows: + +| Format | Message | +| ------ | --- | +| Bytes | 76 66 3 11 0 1 0 0 0 0 0 75 190 | +| Hex | `4c 42 03 0b 00 01 00 00 00 00 00 4b be` | + + + +::: info +All integers are in [little-endian](https://en.wikipedia.org/wiki/Endianness) format eg. (uint16 `1` is represented as `0x01 0x00`). +::: + +The general structure of a message is as follows: + +| Byte position | Description | Type | Example | +| ------------- | ---------------------------------- | ------------------------- | -- | +| 1 | Protocol Version (always 3) | uint8 | 3 | +| 2 -> 3 | Message Length | uint16 | 11 0 | +| 4 -> 5 | Message Type | uint16 | 1 0 | +| 6 -> a | Header Data (field count, fields, data) | uint16, []uint8, []bBytes | 0 0 | +| a -> b | Payload Data (field count, fields, data) | uint16, []uint8, []bBytes | 0 0 | +| b -> n | Checksum | uint16 | 75 190 | + +So the full above example would be: + + diff --git a/devices/api/protocol/prefix.md b/devices/api/protocol/prefix.md new file mode 100644 index 0000000..d0628d5 --- /dev/null +++ b/devices/api/protocol/prefix.md @@ -0,0 +1,15 @@ +--- +outline: [2,3] +--- + +# Prefix + +To aid reading from a possibly noisy byte stream, such as UART, and to increase efficiency, the messages can be prefixed with a set of start bytes. + +`0x4c, 0x42`, or `76, 66`, which is the ASCII representation of `LB`. + +In combination with the protocol version, this allows for a simple check that indicates you are probably looking at the start of a message. + +`0x4c 0x42 0x03` or `76 66 3` for example. + +Communication methods such as I2C or UDP will not include this prefix. diff --git a/devices/api/protocol/stop.md b/devices/api/protocol/stop.md new file mode 100644 index 0000000..d570ddf --- /dev/null +++ b/devices/api/protocol/stop.md @@ -0,0 +1,15 @@ +--- +outline: [2,3] +--- + +# Stop + +The 2 bytes after the prefix and protocol version indicate the length of the message which gives you a stop point. + +In total the first 5 bytes would look something like this with a prefix: + +`0x4c 0x42 0x03 0x0b 0x00` or `76 66 3 11 0`. + +Or with no prefix: + +`0x03 0x0b 0x00` or `3 11 0`. diff --git a/devices/api/protocol/structure.md b/devices/api/protocol/structure.md new file mode 100644 index 0000000..712e720 --- /dev/null +++ b/devices/api/protocol/structure.md @@ -0,0 +1,40 @@ +--- +outline: [2,3] +--- + + + +# Structure + +- Protocol Version: The version of the protocol (always 3). +- Message Length: The length of the message, including the version, header, data, and checksum. +- Message Type: The type of message. This is used to determine how to interpret the message. +- Data: Both data field (header and payload) are made up of the same format: + - Field Count: The number of fields in the data. + - Fields: List of field types in the data + - Data: The data itself, making used of bBytes to represent length and values. +- Checksum: A 16-bit CRC checksum of the message (XMODEM). + +### Data + +Within each Data element (the header data, or payload data), the structure is as follows: + +| Byte position | Description | Type | Example | +| ------------- | ---------------- | ----- | ------- | +| 1 -> 2 | Number of fields (n) | uint16 | 2 0 | +| 3 -> 3+n | Field types | []uint8 | 1 2 | +| 3+n+1 -> end | Data | []bBytes | [1 8] [3 9 9 9] | + +The Data should be in the order of the field types. + +The example data includes `2` data fields, the first of type `1`, with value byte array `[8]`, the second of type `2`, with value byte array `[9 9 9]`. + +#### bBytes + +bBytes are a byte array that represents a length and then the data itself. + +For example, `[1 8]` would represent a byte array of length 1, with the value 8. + +Or `[3 9 9 9]` would represent a byte array of length 3, with the values 9, 9, 9. diff --git a/devices/api/sdks/toit/examples/action-message.md b/devices/api/sdks/toit/examples/action-message.md new file mode 100644 index 0000000..6397da8 --- /dev/null +++ b/devices/api/sdks/toit/examples/action-message.md @@ -0,0 +1,19 @@ +--- +order: 1 +aside: true +outline: deep +--- + +# Action Message + +Send a simple GET message to the Lightbug device. + +## Reset CPU 1 + +### Code + +```toit + +``` + +### Output diff --git a/devices/api/sdks/toit/examples/eink.md b/devices/api/sdks/toit/examples/eink.md deleted file mode 100644 index ace7743..0000000 --- a/devices/api/sdks/toit/examples/eink.md +++ /dev/null @@ -1,96 +0,0 @@ - - -# Eink Hello World - -The latest version of the eink example can be [found on GitHub](https://github.com/lightbug-io/toit-lightbug/blob/main/examples/eink.toit). - - -## Output - -When the program is running, you should see some output through the `monitor` command that looks something like this: - -``` -[lb-comms] INFO: Comms starting -[lb-comms] INFO: Comms started -💬 Sending text page to device -💬 Text page sent -Waiting on message latch -✅ Text page ACKed -Latch response: Message type: 5 length: 40 response-to: 3405447839 -``` - -## Device - -The device EInk screen will update, displaying the text that was included in the message. - - - -## Code - -First, the required dependencies are [imported](https://docs.toit.io/language/imports). - -This primarily includes things from the `lightbug` package, but also the [log library](https://libs.toit.io/log/library-summary) that is part of the toit SDK. - -```toit -import lightbug.devices as devices -import lightbug.services as services -import lightbug.messages as messages -import log -``` - -A `main` function is defined, which is the entry point of the toit program. - -Here we start setting up the application, such as the log level to use, the device to use, and the communication service. - -```toit -main: - // Setup the Toit logger with the INFO log level - log.set-default (log.default.with-level log.INFO-LEVEL) - - // This example is setup to work with the RH2 device - device := devices.RtkHandheld2 - - // Setup the comms service, which allows communication with the Lightbug device - comms := services.Comms --device=device -``` - -We then send a single message to the device, which is a [text page](./../../../messages/10009-text-page.md). - -The `send` function is used to send the message, and it can take a number of optional parameters that allow hooking into the message lifecycle. - -```toit - // Send a basic text page to the device to display - // https://docs.lightbug.io/devices/api/tools/parse?bytes=03%2C57%2C00%2C19%2C27%2C02%2C00%2C05%2C01%2C01%2C01%2C04%2C7f%2C0e%2C60%2C9b%2C05%2C00%2C03%2C04%2C06%2C65%2C66%2C02%2Cd1%2C07%2C0b%2C48%2C65%2C6c%2C6c%2C6f%2C20%2C77%2C6f%2C72%2C6c%2C64%2C01%2C02%2C1f%2C57%2C65%2C6c%2C63%2C6f%2C6d%2C65%2C20%2C74%2C6f%2C20%2C79%2C6f%2C75%2C72%2C20%2C4c%2C69%2C67%2C68%2C74%2C62%2C75%2C67%2C20%2C64%2C65%2C76%2C69%2C63%2C65%2C0c%2C72%2C75%2C6e%2C6e%2C69%2C6e%2C67%2C20%2C54%2C6f%2C69%2C74%2Cb8%2C71 - latch := comms.send (messages.TextPage.to-msg - --page-id=2001 - --page-title="Hello world" - --line2="Welcome to your Lightbug device" - --line3="running Toit" - --redraw-type=2 // FullRedraw - ) - --now=true - --withLatch=true - --preSend=(:: print "💬 Sending text page to device") - --postSend=(:: print "💬 Text page sent") - --onAck=(:: print "✅ Text page ACKed") - --onNack=(:: print "❌ Text page NACKed") - --onError=(:: print "❌ Text page error") -``` - -The code then waits for the message to be responded to, printing the response to the console. - -See [Latch](https://docs.toit.io/language/tasks/#latch) from the Toit [monitor library](https://libs.toit.io/monitor/library-summary). - -```toit - print "Waiting on message latch" - response := latch.get - // The value of the latch will be false on timeout or unknown error, or the msg object for the response - // Such as https://docs.lightbug.io/devices/api/tools/parse?bytes=03%2C28%2C00%2C05%2C00%2C04%2C00%2C03%2C04%2C01%2C02%2C04%2C7f%2C0e%2C60%2C9b%2C01%2C00%2C04%2Cd9%2C16%2C00%2C00%2C08%2Cb3%2Cd5%2C9b%2C00%2C00%2C00%2C00%2C00%2C01%2C00%2C01%2C02%2C19%2C27%2Ca9%2C0c - print "Latch response: $response" -``` diff --git a/devices/api/sdks/toit/examples/get-message.md b/devices/api/sdks/toit/examples/get-message.md new file mode 100644 index 0000000..d544829 --- /dev/null +++ b/devices/api/sdks/toit/examples/get-message.md @@ -0,0 +1,21 @@ +--- +order: 0 +aside: true +outline: deep +--- + +# GET Message + +Send a simple GET message to the Lightbug device. + +## Retrieve IDs + +This is an example of sending a [M35 Device IDs](/devices/api/messages/35-device-ids) message to the Lightbug device, which will return a variety of IDs including the device ID, IMEI, ICCID. + +### Code + +```toit + +``` + +### Output diff --git a/devices/api/sdks/toit/examples/index.md b/devices/api/sdks/toit/examples/index.md index 85e83ee..b5e19ca 100644 --- a/devices/api/sdks/toit/examples/index.md +++ b/devices/api/sdks/toit/examples/index.md @@ -1,5 +1,7 @@ # Examples -The lightbug pkg comes with a variety of examples that can be used to get started with the Lightbug device API. +The lightbug pkg comes with various examples touching on various levels of the device communication and capabilities. These are found in the [examples directory](https://github.com/lightbug-io/toit-lightbug/tree/main/examples) of the pkg, which itself is a standalone Toit package. + +More examples and guides will be included here over time, and if you need specific help, please reach out on Discord. diff --git a/devices/api/sdks/toit/examples/screen-text.md b/devices/api/sdks/toit/examples/screen-text.md new file mode 100644 index 0000000..e949402 --- /dev/null +++ b/devices/api/sdks/toit/examples/screen-text.md @@ -0,0 +1,33 @@ +--- +order: 4 +aside: true +outline: deep +--- + +# Screen text + +Use the `eink` module to display some text on the screen. + +## Code + +```toit + +``` + +## Output + +``` +[jaguar] INFO: program 970dfee5-ec68-d8ad-ade5-06b62aaad39b started +💬 Sending text to device +``` + +## Result + +You should see text drawn on the screen. + +:::tabs +== Graphic +![](https://i.imgur.com/8QP1022.png) +== Photo +![](https://i.imgur.com/7ca0Nda.png){width=500} +::: diff --git a/devices/api/sdks/toit/examples/strobe-flash.md b/devices/api/sdks/toit/examples/strobe-flash.md new file mode 100644 index 0000000..528b1f5 --- /dev/null +++ b/devices/api/sdks/toit/examples/strobe-flash.md @@ -0,0 +1,17 @@ +--- +order: 3 +aside: true +outline: deep +--- + +# Strobe flash + +Use the `strobe` module of the device to flash the strobe in a sequence. + +## Code + +```toit + +``` + +## Output diff --git a/devices/api/sdks/toit/getting-started.md b/devices/api/sdks/toit/getting-started.md index f503c4b..6fa92bf 100644 --- a/devices/api/sdks/toit/getting-started.md +++ b/devices/api/sdks/toit/getting-started.md @@ -1,11 +1,17 @@ # Getting started +::: warning ⚠️ main branch documentation +This documentation is currently for the `main` branch of the Toit SDK, which is under active development. + +There are pinned early releases available, but they may be out of date in comparison to this documentation. +::: + ### 1. Get an ESP32 enabled device -ESP32s are being introduced on some Lightbug devices. +ESP32s are being introduced on some Lightbug devices, such as the [RTK handheld (RH2)](/devices/rtk/). -You'll need one of these devices to run Toit on a Lightbug device. +You'll need one of these devices to run Toit code on. ### 2. Install Jaguar @@ -14,16 +20,16 @@ You'll need one of these devices to run Toit on a Lightbug device. Install Jaguar, [following step 2](https://docs.toit.io/getstarted/device/#2-install-jaguar) in the Toit getting started guide. ::: info -We currently require `v1.50.3`+ of Jaguar, which bundles at least `v2.0.0-alpha.179` of Toit. +We currently recommend `v1.55.0`+ of Jaguar, which bundles at least `v2.0.0-alpha.188` of Toit. ::: Once installed, you should be able to run the version command: ```sh jag version -Version: v1.50.3 -SDK version: v2.0.0-alpha.179 -Build date: 2025-04-31T10:10:10Z +Version: v1.55.0 +SDK version: v2.0.0-alpha.188 +Build date: 2025-08-20T08:35:24Z ``` ### 3. Flash the ESP @@ -44,6 +50,38 @@ After flashing, your device boots up and starts the Toit virtual machine. The Ja You can see what the ESP is doing by monitoring the serial output of the device with the `jag monitor` command. +
+Click to see example `jag monitor` output + +``` +Starting serial monitor of port 'COM22' ... +[wifi] DEBUG: connected +ESP-ROM:esp32c6-20220919 +Build:Sep 19 2022 +rst:0x15 (USB_UART_HPSYS),boot:0x6f (SPI_FAST_FLASH_BOOT) +Saved PC:0x4081306a +SPIWP:0xee +mode:DIO, clock dESP-ROM:esp32c6-20220919 +Build:Sep 19 2022 +rst:0x15 (USB_UART_HPSYS),boot:0x6f (SPI_FAST_FLASH_BOOT) +Saved PC:0x400294a2 +SPIWP:0xee +mode:DIO, clock div:2 +load:0x40875720,len:0x9c +load:0x4086c110,len:0xb94 +load:0x4086e610,len:0x2534 +entry 0x4086c110 +[toit] INFO: starting +[toit] DEBUG: clearing RTC memory: powered on by hardware source +[toit] INFO: running on ESP32C6 - revision 0.1 +[wifi] DEBUG: connecting +[wifi] DEBUG: connected +[wifi] INFO: network address dynamically assigned through dhcp {ip: 192.168.68.50} +[wifi] INFO: dns server address dynamically assigned through dhcp {ip: [8.8.8.8, 1.1.1.1]} +[jaguar.http] INFO: running Jaguar device 'long-expert' (id: '736b8804-dcdf-4d96-890a-8785c1bfa31d') on 'http://192.168.68.50:9000' +``` +
+ ::: tip Leave the terminal with `jag monitor` running open, as it will show you the output of the device, and will also show you the output of the code you run on the device. ::: @@ -65,10 +103,10 @@ VERSION=$(jag pkg search lightbug-io/toit-lightbug | awk '{print $3}') jag pkg install github.com/lightbug-io/toit-lightbug@$VERSION ``` -You can copy the example [eink based Hello World application](https://github.com/lightbug-io/toit-lightbug/blob/main/examples/eink.toit) for the RTK Handheld 2 device into your project with the following command: +You can copy the example [eink based Hello World application](https://github.com/lightbug-io/toit-lightbug/blob/main/examples/modules/eink/element-box-text.toit) into your project with the following command: ```sh -cp ./.packages/github.com/lightbug-io/toit-lightbug/$VERSION/examples/eink.toit ./main.toit +cp ./.packages/github.com/lightbug-io/toit-lightbug/$VERSION/examples/modules/eink/element-box-text.toit ./main.toit ``` ### 6. Run the code @@ -84,14 +122,19 @@ If your device can not be found automatically, you can specify the device IP add Once the code is running, you should see some output through the `monitor` command you ran earlier. ``` -[jaguar] INFO: program cf533602-d549-c9bd-34a3-3ae1093bda51 started -[lb-comms] INFO: Comms starting -[lb-comms] INFO: Comms started -💬 Sending text page to device -💬 Text page sent -Waiting on message latch -✅ Text page ACKed -Latch response: Message type: 5 length: 40 response-to: 3405447839 +[jaguar] INFO: program 970dfee5-ec68-d8ad-ade5-06b62aaad39b started +💬 Sending text to device ``` -And you should see the device screen update +And you should see the device screen update, saying `Lightbug...` in the top left. + +:::tabs +== Graphic +![](https://i.imgur.com/8QP1022.png) +== Photo +![](https://i.imgur.com/7ca0Nda.png){width=500} +::: + +:::tip +You can also see this code [under the examples section](/devices/api/sdks/toit/examples/screen-text). +::: diff --git a/devices/api/sdks/toit/index.md b/devices/api/sdks/toit/index.md index be0bedb..da787fd 100644 --- a/devices/api/sdks/toit/index.md +++ b/devices/api/sdks/toit/index.md @@ -9,3 +9,38 @@ Lightbug provides a [Toit package](https://pkg.toit.io/package/github.com%2Fligh Together, these tools allow you to quickly develop and deploy applications on Lightbug devices using Toit. Once developed, Toit firmware can be build without the jaguar development tooling enabled, and sent to Lightbug devices over the air for update. + +:::tip + +Access to the device API is not limited to Toit, however it is the current preferred and documented high-level language for Lightbug devices. + +Devices with an ESP32 can also be programmed using C/C++ with the ESP-IDF framework, or anything else that is supported on the ESP32. For such solutions, you'll need to make use of the lower level [messages](./../../messages/), rather than a higher level abstraction like the Toit package. + +::: + +Interacting with the device using the Toit SDK can be as simple as this to draw some text on the screen: + +```toit +import lightbug.devices as devices +import lightbug.messages.messages_gen as messages + +main: + device := devices.I2C + device.eink.draw-element --status-bar-enable=false --type=messages.DrawElement.TYPE_BOX --x=0 --y=0 --text="Lightbug..." + while true: + sleep --ms=1000 +``` + +Or this to subscribe to button press events: + +```toit +import lightbug.devices as devices + +main: + device := devices.I2C + device.buttons.subscribe --callback=(:: |button-data| + print "Button pressed: (ID: $button-data.button-id)" + ) + while true: + sleep --ms=1000 +``` diff --git a/devices/api/structure.md b/devices/api/structure.md deleted file mode 100644 index 8c75c6a..0000000 --- a/devices/api/structure.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -outline: [2,3] ---- - - - -# Structure - -::: info -All integers are in [little-endian](https://en.wikipedia.org/wiki/Endianness) format eg. (uint16 `1` is represented as `0x01 0x00`). -::: - -In a byte stream, a message takes the follow structure: - -``` -
-> -``` - -The header data, and payload data, are made up of the same structure: - -``` - -``` - -As an example empty message including prefix (with no additional header or payload data): - - - -## Prefix - -To aid reading from a possibly noisy byte stream, such as UART, and to increase efficiency, the messages can be prefixed with a set of start bytes. - -`0x4c, 0x42`, or `76, 66`, which is the ASCII representation of `LB`. - -In combination with the protocol version, this allows for a simple check that indicates you are probably looking at the start of a message. - -`0x4c 0x42 0x03` or `76 66 3` for example. - -Communication methods such as I2C or UDP will not include this prefix. - -## Stop - -The 2 bytes after the prefix and protocol version indicate the length of the message which gives you a stop point. - -In total the first 5 bytes would look something like this with a prefix: - -`0x4c 0x42 0x03 0x0b 0x00` or `76 66 3 11 0`. - -Or with no prefix: - -`0x03 0x0b 0x00` or `3 11 0`. - -## Message - -The general structure of a message is as follows: - -| Byte position | Description | Type | Example | -| ------------- | ---------------------------------- | ------------------------- | -- | -| 1 | Protocol Version (always 3) | uint8 | 3 | -| 2 -> 3 | Message Length | uint16 | 11 0 | -| 4 -> 5 | Message Type | uint16 | 1 0 | -| 6 -> a | Header Data (field count, fields, data) | uint16, []uint8, []bBytes | 0 0 | -| a -> b | Payload Data (field count, fields, data) | uint16, []uint8, []bBytes | 0 0 | -| b -> n | Checksum | uint16 | 75 190 | - -So the full above example would be: - - - -## Components - -- Protocol Version: The version of the protocol. Always 3. -- Message Length: The length of the message, including the version, header, data, and checksum. -- Message Type: The type of message. This is used to determine how to interpret the message. (See [Message Types](#message-types) below.) -- Data: Both data field (header and payload) are made up of the same format: - - Field Count: The number of fields in the data. - - Fields: List of field types in the data - - Data: The data itself, making used of bBytes to represent length and values. -- Checksum: A 16-bit CRC checksum of the message (XMODEM). - -### Data - -Within each Data element (the header data, or payload data), the structure is as follows: - -| Byte position | Description | Type | Example | -| ------------- | ---------------- | ----- | ------- | -| 1 -> 2 | Number of fields (n) | uint16 | 2 0 | -| 3 -> 3+n | Field types | []uint8 | 1 2 | -| 3+n+1 -> end | Data | []bBytes | [1 8] [3 9 9 9] | - -The Data should be in the order of the field types. - -The example data includes `2` data fields, the first of type `1`, with value byte array `[8]`, the second of type `2`, with value byte array `[9 9 9]`. - -#### bBytes - -bBytes are a byte array that represents a length and then the data itself. - -For example, `[1 8]` would represent a byte array of length 1, with the value 8. - -Or `[3 9 9 9]` would represent a byte array of length 3, with the values 9, 9, 9. - -## Examples - -#### Type 3, header empty, data empty - - - -#### .. as above, with LB prefix bytes: - - - -#### Type 6, header (1:1), data empty - - - -#### Type 6, header (1:9), data empty - - - -#### Type 10009, header empty, data (10:hello): - - diff --git a/devices/enviro/index.md b/devices/enviro/index.md index 5c22b51..4c9cc29 100644 --- a/devices/enviro/index.md +++ b/devices/enviro/index.md @@ -1,3 +1,7 @@ +--- +aside: false +--- + + + diff --git a/devices/rtk/handheld/screen.md b/devices/rtk/handheld/screen.md new file mode 100644 index 0000000..3a27ddb --- /dev/null +++ b/devices/rtk/handheld/screen.md @@ -0,0 +1,85 @@ +--- +aside: true +outline: deep +--- + +# Screen + +The RH2 features a 2.13" monochrome e-ink display with a resolution of 250x122 pixels, which is visible in direct sunlight and has a very low power consumption. + +The default firmware of the RH2 has a simple user interface that makes use of the screen to display information such as GNSS status, battery level, and allow basic control of the device. + +The screen can also be used by the ESP32 microcontroller as part of a custom application, for example to display sensor data, custom menus, alerts, messaging and more. + +## Defaults + +The default firmware has a single main [home](#home) screen, with a sub [menu](#menu) screen. + +### Home + +The home screen shows basic device status, and basic device control. + +The status bar at the top shows: + - SIM status + - GSM status and signal strength + - Battery level + - Charge state + +#### Disarmed + +A device would normally start in a disarmed state. + +In this state the device is not attempting to get a GNSS fix or report its location, or connect to GSM. + +:::tabs +== Visualization +![](https://i.imgur.com/lGxzg9U.png) +== Wide Photo +![](https://i.imgur.com/dF5X5Qn.png) +== Zoom Photo +![](https://i.imgur.com/42e4q6P.jpeg) +::: + +The center button can be used to arm the device (See [armed](#armed) below). + +Or the menu button can be used to access the [menu](#menu) below. + +The actions selection currently does nothing, and is intended for future use. + +#### Armed + +When armed the device will find it location using GNSS, and report it to the Lightbug Cloud, then streaming RTK corrections if available for the device. + +Information above the status of this process will be shown on the screen. + +:::tabs +== Visualization +![](https://i.imgur.com/C05HoGx.png) +== Wide Photo +![](https://i.imgur.com/gnhrnfH.png) +== Zoom Photo +![](https://i.imgur.com/1hVj0c0.jpeg) +::: + + +### Menu + +The menu allows selection of: + - Base station mode (allowing the device to work as an RTK base station) + - 1Hz RTK tracking + - 2Hz RTK tracking + - 5Hz RTK tracking + - Displays the Device ID + +:::tabs +== Visualization +![](https://i.imgur.com/pZ22H5j.png) +== Wide Photo +![](https://i.imgur.com/D0PxTPE.png) +== Zoom Photo +![](https://i.imgur.com/a0mwlDn.jpeg) +::: + +## Custom + +Custom applications running on the [ESP32](esp32) can make use of [Toit SDK](/devices/api/sdks/toit/) and or [device API](/devices/api/) to draw custom screens. diff --git a/devices/rtk/index.md b/devices/rtk/index.md index 59c9c15..0b69f30 100644 --- a/devices/rtk/index.md +++ b/devices/rtk/index.md @@ -1,6 +1,7 @@ - +--- +title: RTK +layout: full +fullWidth: true +--- - +# RTK diff --git a/devices/rtk/vehicle.md b/devices/rtk/vehicle.md new file mode 100644 index 0000000..6a2ba89 --- /dev/null +++ b/devices/rtk/vehicle.md @@ -0,0 +1,9 @@ +--- +aside: false +--- + +# Powered Vehicle RTK (VTRTK) + +A powered RTK tracker for vehicles, with advanced GNSS and RTK capabilities. + +Currently available for demo, with the form factor of a [VT3](/devices/vehicle/) device, and capabilities of an [RH2](/devices/rtk/handheld/) device. diff --git a/devices/vehicle/index.md b/devices/vehicle/index.md index a178001..a9f8bfd 100644 --- a/devices/vehicle/index.md +++ b/devices/vehicle/index.md @@ -1,4 +1,6 @@ --- + +aside: false next: text: 'Installation' link: '/devices/vehicle/installation' diff --git a/devices/vehicle/installation.md b/devices/vehicle/installation.md index 4c5c161..3a4295c 100644 --- a/devices/vehicle/installation.md +++ b/devices/vehicle/installation.md @@ -11,56 +11,9 @@ If you purchase a vehicle tracker today, you will receive the VT3 device. ## Tools -You will likely need the following tools to complete installation. +You will likely need the following tools to complete installation: - - - - - - - - - +![](https://i.imgur.com/rKFNxsu.png){width=300 style="float:right"} - Long Nose Pliers - Wire cutters or strippers diff --git a/devices/zero/index.md b/devices/zero/index.md index 11946db..0934cb8 100644 --- a/devices/zero/index.md +++ b/devices/zero/index.md @@ -1,3 +1,7 @@ +--- +aside: false +--- +