diff --git a/content/models/PCA20035+solar.md b/content/models/PCA20035+solar.md deleted file mode 100644 index a98a7db0..00000000 --- a/content/models/PCA20035+solar.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Thingy:91 with Solar Shield -tagline: Powerfoyle solar cell converts any form of light to electrical energy -links: - learnMore: https://www.exeger.com/updates/exeger-and-nordic-semiconductor-in-partnership/ - documentation: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug_thingy91%2FUG%2Fthingy91%2Fintro%2Ffrontpage.html -firmware: - version: 1.1.3 - link: https://github.com/hello-nrfcloud/firmware/releases/tag/v1.1.3 - upgradePath: - ">=0.0.0": APP*962abcac*v1.1.3-sol-lp-mmflt - important: false -mfw: - version: 1.3.6 - link: https://www.nordicsemi.com/Products/Development-hardware/Nordic-Thingy-91/Download?lang=en#infotabs - upgradePath: - ">=0.0.0": MDM_FULL*551ba99b*mfw_nrf9160_full_1.3.6 - important: false -abstract: >- - The Nordic Thingy:91 has been fitted with a light harvesting add-on, giving - the platforms autonomous charging capabilities. -video: - youtube: - id: 5f10sjTznlc - title: Getting Started with the Nordic Thingy:91 and Powerfoyle Shield -includedSIMs: - - ibasis -defaultConfiguration: - updateIntervalSeconds: 120 - gnssEnabled: true -configurationPresets: - - name: Real-time mode - updateIntervalSeconds: 10 - dataUsagePerDayMB: 3 - - name: Interactive mode - updateIntervalSeconds: 120 - dataUsagePerDayMB: 1.5 - - name: Low-power mode - updateIntervalSeconds: 600 - dataUsagePerDayMB: 0.05 - - name: Ultra-Low-power mode - updateIntervalSeconds: 3600 - dataUsagePerDayMB: 0.01 ---- - -The Nordic Thingy:91 Solar Shield is a plug-and-play prototyping platform. -Powerfoyle solar cell is mounted onto the Thingy to quickly get started -exploring the endless possibilities with solar powered IoT applications and to -develop products with eternal life or even battery-free products.​ - -The Thingy:91 runs the -[`asset_tracker_v2` application](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/applications/asset_tracker_v2/README.html) -configured in low-power mode, requires 3.4 mA when sending updates to the cloud -every minute, or 2.3 mA when sending updates to the cloud every hour. - -Powerfoyle is a groundbreaking solar cell technology made by Exeger. Powerfoyle -has a uniquely flexible and customizable design to integrate seamlessly for -sustainable and attractive products. To learn more the innovation and -application areas, visit [www.exeger.com](https://www.exeger.com/).​ - -## Demo devices - -Here are some demo devices you can view: - -- [SOL-TRD#1](/1.phxf9c) diff --git a/src/model/PCA20035-solar/Battery.tsx b/src/model/PCA20035-solar/Battery.tsx deleted file mode 100644 index 94f59146..00000000 --- a/src/model/PCA20035-solar/Battery.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Ago } from '#components/Ago.js' -import { BatteryIndicator } from '#components/BatteryIndicator.js' -import { LoadingIndicator } from '#components/ValueLoading.js' -import { useDevice } from '#context/Device.js' -import { isBatteryAndPower, toBatteryAndPower } from '#proto/lwm2m.js' - -export const Battery = () => ( - <> -

Battery

-

- -

-

- - This is the value reported by the PMIC's fuel gauge function that - represents the charge level of the battery in percent. - -

- -) - -const BatteryInfo = () => { - const { reported } = useDevice() - const batteryReading = Object.values(reported) - .filter(isBatteryAndPower) - .map(toBatteryAndPower)[0] - - if (batteryReading?.['%'] === undefined) - return - return ( - - - {batteryReading['%']} %{' '} - - - - - ) -} diff --git a/src/model/PCA20035-solar/Chart.tsx b/src/model/PCA20035-solar/Chart.tsx deleted file mode 100644 index 8dd95533..00000000 --- a/src/model/PCA20035-solar/Chart.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { DateRangeButton } from '#chart/DateRangeButton.js' -import { HistoryChart } from '#chart/HistoryChart.js' -import { timeSpans } from '#chart/timeSpans.js' -import { Ago } from '#components/Ago.js' -import { WithResize } from '#components/ResizeObserver.js' -import { LoadingIndicator } from '#components/ValueLoading.js' -import { WaitingForData } from '#components/WaitingForData.js' -import { useDevice } from '#context/Device.js' -import { useHistoryChart } from '#context/HistoryChart.js' -import { useHistory } from '#model/PCA20035-solar/HistoryContext.js' -import { toChartData } from '#model/PCA20035-solar/toChartData.js' -import { - byTimestamp, - isBatteryAndPower, - isSolarCharge, - toBatteryAndPower, - toSolarCharge, -} from '#proto/lwm2m.js' -import { formatFloat } from '#utils/format.js' -import { BatteryCharging, Sun } from 'lucide-preact' - -export const Chart = () => ( - <> - -
-
-
-
- -
-
-
-
- -) - -const SolarChart = () => { - const { battery, gain } = useHistory() - const { timeSpan, setTimeSpan } = useHistoryChart() - - const hasChartData = gain.length + battery.length > 0 - - return ( -
-
- {hasChartData && ( - - {(size) => ( - - )} - - )} - {!hasChartData && ( -
- -
- )} -
-
-
- Chart history: - {timeSpans.map(({ id, title }) => ( - { - setTimeSpan(id) - }} - label={title} - active={timeSpan === id} - /> - ))} -
-
-
- ) -} - -const FirmwareInfo = () => { - const { reported } = useDevice() - - const currentBattery = Object.values(reported) - .filter(isBatteryAndPower) - .sort(byTimestamp) - .map(toBatteryAndPower)[0] - const currentGain = Object.values(reported) - .filter(isSolarCharge) - .sort(byTimestamp) - .map(toSolarCharge)[0] - - return ( - <> -

- The Thingy:91 runs the{' '} - - asset_tracker_v2 - {' '} - application configured in low-power mode, requires 3.4 mA when sending - updates to the cloud every minute, or 2.3 mA when sending updates to the - cloud every hour. -

-
- <> -
- Gain -
-
- {currentGain === undefined && } - {currentGain !== undefined && ( - <> - {formatFloat(currentGain.mA)} mA - - - - - )} -
- - <> -
- Battery -
-
- {currentBattery === undefined && } - {currentBattery !== undefined && ( - <> - {currentBattery['%']} %{' '} - - - - - )} -
- -
- - ) -} diff --git a/src/model/PCA20035-solar/ConnectionSuccess.tsx b/src/model/PCA20035-solar/ConnectionSuccess.tsx deleted file mode 100644 index 32faff4f..00000000 --- a/src/model/PCA20035-solar/ConnectionSuccess.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { CloudUpload } from 'lucide-preact' - -export const ConnectionSuccess = () => ( -
-

- Success! -

-

- Your device connected and is sending data to the cloud! You can learn more - about some of it's features below. -

-
-) diff --git a/src/model/PCA20035-solar/HistoryContext.tsx b/src/model/PCA20035-solar/HistoryContext.tsx deleted file mode 100644 index 7009760d..00000000 --- a/src/model/PCA20035-solar/HistoryContext.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { getObjectHistory } from '#api/getObjectHistory.js' -import { useDevice, type ListenerFn } from '#context/Device.js' -import { useFingerprint } from '#context/Fingerprint.js' -import { useHistoryChart } from '#context/HistoryChart.js' -import { useParameters } from '#context/Parameters.js' -import { - isBatteryAndPower, - isSolarCharge, - isTime, - timeToDate, - toBatteryAndPower, - toSolarCharge, - type BatteryAndPower, - type SolarCharge, -} from '#proto/lwm2m.js' -import { byTs } from '#utils/byTs.js' -import { LwM2MObjectID } from '@hello.nrfcloud.com/proto-map/lwm2m' -import { isNumber, isObject } from 'lodash-es' -import { createContext, type ComponentChildren } from 'preact' -import { useContext, useEffect, useState } from 'preact/hooks' - -export type BatteryReading = BatteryAndPower -export type BatteryReadings = Array -export type GainReading = SolarCharge -export type GainReadings = Array - -export const HistoryContext = createContext<{ - battery: BatteryReadings - gain: GainReadings -}>({ - battery: [], - gain: [], -}) - -export const Provider = ({ children }: { children: ComponentChildren }) => { - const { onReported, device } = useDevice() - const { fingerprint } = useFingerprint() - const { onParameters } = useParameters() - const { timeSpan } = useHistoryChart() - - const [battery, setBattery] = useState([]) - const [gain, setGain] = useState([]) - - const listener: ListenerFn = (instance) => { - if (isBatteryAndPower(instance)) { - setBattery((b) => [toBatteryAndPower(instance), ...b].sort(byTs)) - } - if (isSolarCharge(instance)) { - setGain((b) => [toSolarCharge(instance), ...b].sort(byTs)) - } - } - - useEffect(() => { - const { remove } = onReported(listener) - if (device === undefined) return - if (fingerprint === null) return - - onParameters(({ helloApiURL }) => { - const g = getObjectHistory(helloApiURL, device, fingerprint) - g(LwM2MObjectID.SolarCharge_14210, timeSpan).ok( - ({ partialInstances }) => { - setGain( - partialInstances - .filter(isGain) - .map(({ '0': mA, '99': ts }) => ({ - mA, - ts: timeToDate(ts), - })) - .sort(byTs), - ) - }, - ) - g(LwM2MObjectID.BatteryAndPower_14202, timeSpan).ok( - ({ partialInstances }) => { - setBattery( - partialInstances - .filter(isBattery) - .map(({ '0': SoC, '99': ts }) => ({ - '%': SoC, - ts: timeToDate(ts), - })) - .sort(byTs), - ) - }, - ) - }) - - return () => { - remove() - } - }, [timeSpan]) - - return ( - - {children} - - ) -} - -const isGain = (o: unknown): o is { 0: number; 99: number } => - isObject(o) && '0' in o && isNumber(o['0']) && '99' in o && isTime(o['99']) - -const isBattery = (o: unknown): o is { 0: number; 99: number } => - isObject(o) && '0' in o && isNumber(o['0']) && '99' in o && isTime(o['99']) - -export const Consumer = HistoryContext.Consumer - -export const useHistory = () => useContext(HistoryContext) diff --git a/src/model/PCA20035-solar/Page.css b/src/model/PCA20035-solar/Page.css deleted file mode 100644 index 56ab4b5a..00000000 --- a/src/model/PCA20035-solar/Page.css +++ /dev/null @@ -1,7 +0,0 @@ -@media (min-width: 992px) { - .gridSolar { - display: grid; - grid-template: auto auto / 1fr 1fr; - grid-auto-flow: column; - } -} diff --git a/src/model/PCA20035-solar/Page.tsx b/src/model/PCA20035-solar/Page.tsx deleted file mode 100644 index d1ea9975..00000000 --- a/src/model/PCA20035-solar/Page.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { BME680 } from '#components/BME680.js' -import { Configuration } from '#components/Configuration.js' -import { DeviceHeader } from '#components/DeviceHeader.js' -import { HideDataBefore } from '#components/HideDataBefore.js' -import { IncludedSIMs } from '#components/IncludedSIMInfo.js' -import { Troubleshooting } from '#components/Troubleshooting.js' -import { NetworkInfo } from '#components/deviceInfo/NetworkInfo.js' -import { DeviceFOTAInfo } from '#components/fota/DeviceFOTAInfo.js' -import { QuickGlance } from '#components/quickGlance/QuickGlance.js' -import { useDevice, type Device as TDevice } from '#context/Device.js' -import { DeviceMap } from '#map/DeviceMap.js' -import { LocationHelp } from '#map/LocationHelp.js' -import { ModelCard } from '#model/ModelCard.js' -import { Battery } from '#model/PCA20035-solar/Battery.js' -import { Chart } from '#model/PCA20035-solar/Chart.js' -import { ConnectionSuccess } from '#model/PCA20035-solar/ConnectionSuccess.js' -import { Provider as HistoryContextProvider } from '#model/PCA20035-solar/HistoryContext.js' - -import './Page.css' - -export const Page = ({ device }: { device: TDevice }) => { - const { hasLiveData } = useDevice() - return ( - -
-
-
-
- - - {!hasLiveData && } - {hasLiveData && } -
-
- -
-
- {device.model.includedSIMs.length > 0 && !hasLiveData && ( -
-
-

Included SIMs

- -
-
- )} -
-
- - -
-
-
- -
-
-
-
-
-
-
-
- -
-
- -
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
-
-
- ) -} diff --git a/src/model/PCA20035-solar/toChartData.ts b/src/model/PCA20035-solar/toChartData.ts deleted file mode 100644 index 8ef72d75..00000000 --- a/src/model/PCA20035-solar/toChartData.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { TimeSpan } from '#api/api.js' -import type { ChartData } from '#chart/chartMath.js' -import { xAxisForType } from '#chart/xAxisForType.js' -import { - type BatteryReading, - type BatteryReadings, - type GainReadings, -} from '#model/PCA20035-solar/HistoryContext.js' -import { formatFloat } from '#utils/format.js' -import { subHours, subMilliseconds } from 'date-fns' - -export const toChartData = ({ - battery, - gain, - type, -}: { - battery: BatteryReadings - gain: GainReadings - type: TimeSpan -}): ChartData => { - const base = new Date( - battery[battery.length - 1]?.ts ?? subHours(new Date(), 1).getTime(), - ) - - const stateOfCharge = battery.filter(hasStateOfCharge) - - return { - xAxis: xAxisForType(type), - datasets: [ - // Gain - { - min: 0, - max: 6.5, - values: gain.map(({ mA, ts }) => [ - mA, - subMilliseconds(base, base.getTime() - ts.getTime()), - ]), - color: 'var(--color-nordic-sun)', - format: (v) => `${formatFloat(v)} mA`, - helperLines: [ - { - label: '1m', - value: 3.4, // gainReferenceEveryMinute - }, - { - label: '60m', - value: 2.3, // gainReferenceEveryHour - }, - ], - }, - // Battery percentage - { - min: 0, - max: 100, - values: stateOfCharge.map(({ '%': percent, ts }) => [ - percent, - subMilliseconds(base, base.getTime() - ts.getTime()), - ]), - color: 'var(--color-nordic-grass)', - format: (v) => `${v} %`, - }, - ], - } -} - -const hasStateOfCharge = ( - message: BatteryReading, -): message is { '%': number; ts: Date } => '%' in message diff --git a/src/page/Device.tsx b/src/page/Device.tsx index d1c28d71..3fe6b02d 100644 --- a/src/page/Device.tsx +++ b/src/page/Device.tsx @@ -7,7 +7,6 @@ import { useDevice } from '#context/Device.js' import { Provider as FOTAProvider } from '#context/FOTA.js' import { useFingerprint } from '#context/Fingerprint.js' import { WithParameters } from '#context/Parameters.js' -import { Page as SolarThingy91 } from '#model/PCA20035-solar/Page.js' import { Page as Thingy91X } from '#model/PCA20065/Page.js' import cx from 'classnames' @@ -47,9 +46,6 @@ export const Device = () => { helloApiURL={helloApiURL} >
- {device.model.slug === 'PCA20035+solar' && ( - - )} {device.model.slug === 'PCA20065' && ( )} diff --git a/src/page/ViewSource.tsx b/src/page/ViewSource.tsx index beca0694..20238968 100644 --- a/src/page/ViewSource.tsx +++ b/src/page/ViewSource.tsx @@ -244,7 +244,7 @@ export const ViewSource = () => ( as well as render static pages (for example for the development kit pages){' '} using Markdown files diff --git a/src/proto/lwm2m.ts b/src/proto/lwm2m.ts index 9e2ff35f..1f88652e 100644 --- a/src/proto/lwm2m.ts +++ b/src/proto/lwm2m.ts @@ -13,7 +13,6 @@ import { type NRFCloudServiceInfo_14401, type Reboot_14250, type RGBLED_14240, - type SolarCharge_14210, } from '@hello.nrfcloud.com/proto-map/lwm2m' import { isNumber, isObject } from 'lodash-es' @@ -40,9 +39,6 @@ export const isDeviceInformation = isLwM2MObject( export const isEnvironment = isLwM2MObject( LwM2MObjectID.Environment_14205, ) -export const isSolarCharge = isLwM2MObject( - LwM2MObjectID.SolarCharge_14210, -) export const isButtonPress = isLwM2MObject( LwM2MObjectID.ButtonPress_14220, ) @@ -88,16 +84,6 @@ export const toBatteryAndPower = ( ts: timeToDate(instance['Resources'][99]), }) -export type SolarCharge = WithTimestamp & { - mA: number - V?: number -} -export const toSolarCharge = (instance: SolarCharge_14210): SolarCharge => ({ - mA: instance['Resources'][0], - V: instance['Resources'][1], - ts: timeToDate(instance['Resources'][99]), -}) - export type Environment = WithTimestamp & Partial<{ // airHumidityReading diff --git a/src/proto/validPassthrough.spec.ts b/src/proto/validPassthrough.spec.ts index 94f70ac3..c7a6e12b 100644 --- a/src/proto/validPassthrough.spec.ts +++ b/src/proto/validPassthrough.spec.ts @@ -9,13 +9,13 @@ void describe('validPassthrough', () => { void it('should let valid input pass', () => { const isValid = validPassthrough({ '@context': 'https://github.com/hello-nrfcloud/proto/deviceIdentity', - model: 'PCA20035+solar', + model: 'PCA20065', id: 'oob-352656108602296', lastSeen: '2024-05-23T12:27:19.400Z', }) assert.deepEqual(isValid, { '@context': 'https://github.com/hello-nrfcloud/proto/deviceIdentity', - model: 'PCA20035+solar', + model: 'PCA20065', id: 'oob-352656108602296', lastSeen: '2024-05-23T12:27:19.400Z', }) diff --git a/static/images/PCA20035+solar-QR.webp b/static/images/PCA20035+solar-QR.webp deleted file mode 100644 index 6f59cedb..00000000 Binary files a/static/images/PCA20035+solar-QR.webp and /dev/null differ diff --git a/static/images/PCA20035+solar.webp b/static/images/PCA20035+solar.webp deleted file mode 100644 index 6b6bffa7..00000000 Binary files a/static/images/PCA20035+solar.webp and /dev/null differ