From f5bc230fb6644bc5bc4becf9aaf908dca67c1209 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 24 Jun 2025 11:01:37 -0600 Subject: [PATCH 01/11] changed test button to load scans --- package-lock.json | 2 +- src/pages/Device.tsx | 5 ++++- src/providers/pond/deviceAPI.tsx | 17 ++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 064fad0..407efa0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10864,7 +10864,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#b7bf189d71066fd840b9a34e06c29134fdd7f00b", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#a565b6b7382543f1b71ed6f55ff213ccf2d41c5b", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index c6598fa..e50469b 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -390,6 +390,8 @@ export default function DevicePage() { refreshCallback={loadDevice} /> + {/* add grid card here for I2C detected components */} + {diagnosticComponents.map(comp => ( { - deviceAPI.detectI2C(device.id()).then(resp => {console.log("No errors")}).catch(err => {console.log("error")}) + //deviceAPI.detectI2C(device.id()).then(resp => {console.log("No errors")}).catch(err => {console.log("error")}) + deviceAPI.listFoundComponents(device.id()).then(resp => console.log(resp)).catch(err => {console.log("errors")}) }} isPaused={false} isLoading={loading} diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 512fad2..7b7384c 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -23,6 +23,7 @@ export interface IDeviceAPIContext { ) => Promise>; getMulti: (ids: number[] | string[], otherTeam?: string) => Promise>; detectI2C: (id: number, otherTeam?: string) => Promise>; + listFoundComponents: (is: number, otherTeam?: string) => Promise> getGeoJson: (id: number | string, demo?: boolean, otherTeam?: string) => Promise; getMultiGeoJson: (ids: number[] | string[], otherTeam?: string) => Promise; list: ( @@ -960,6 +961,19 @@ export default function DeviceProvider(props: PropsWithChildren) { }) } + const listFoundComponents = (id: number, otherTeam?: string) => { + let url = "/devices/" + id + "/listScannedComponents"; + const view = otherTeam ? otherTeam : as + if(view) url = url + "?as=" + view + return new Promise>((resolve, reject) => { + get(pondURL(url)).then(resp => { + return resolve(resp) + }).catch(err => { + return reject(err) + }) + }) + } + return ( ) { buyData, updateComponentPreferences, listDeviceComponentPreferences, - detectI2C + detectI2C, + listFoundComponents }}> {children} From b314069c861239c8bdfed7fd63549b0a1416953c Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 24 Jun 2025 11:16:44 -0600 Subject: [PATCH 02/11] fix open weather ci variable --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 67d05d8..ee5b194 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", + "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", "build:offline": "npx env-cmd offline,whitelabel npm run build", "test": "vitest" }, From 898bb9e0f1259cd6a7d623f8105b647a665aded3 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 24 Jun 2025 11:17:36 -0600 Subject: [PATCH 03/11] fix open weather CI variable again --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7f976d1..d297090 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", + "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", "build:offline": "npx env-cmd offline,whitelabel npm run build", "test": "vitest" }, From 751b39d34528ecf0e60bbc92bfbd90db2ac0182d Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:20:10 -0600 Subject: [PATCH 04/11] made the react components to display the card for scanned components --- src/apiDocs/enumerators/generalEnums.tsx | 8 +- src/bin/BinComponents.tsx | 2 +- src/device/DeviceWizard.tsx | 21 +++- .../autoDetect/DeviceScannedComponents.tsx | 93 +++++++++++++++ src/device/autoDetect/ScannedI2C.tsx | 107 ++++++++++++++++++ src/models/Component.ts | 30 +++++ src/models/Device.ts | 15 +++ src/pages/Device.tsx | 30 ++++- src/pbHelpers/AddressTypes/I2C.ts | 2 +- src/pbHelpers/DeviceAvailability.ts | 2 +- src/products/Bindapt/BindaptAvailability.ts | 21 ++-- src/products/DeviceProduct.ts | 2 +- src/products/Nexus/NexusAvailability.ts | 2 +- src/providers/pond/deviceAPI.tsx | 2 +- 14 files changed, 311 insertions(+), 26 deletions(-) create mode 100644 src/device/autoDetect/DeviceScannedComponents.tsx create mode 100644 src/device/autoDetect/ScannedI2C.tsx diff --git a/src/apiDocs/enumerators/generalEnums.tsx b/src/apiDocs/enumerators/generalEnums.tsx index 873cd95..c52974b 100644 --- a/src/apiDocs/enumerators/generalEnums.tsx +++ b/src/apiDocs/enumerators/generalEnums.tsx @@ -555,10 +555,10 @@ const componentType: data = { key: "COMPONENT_TYPE_CAPACITANCE", val: 24 }, - { - key: "COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT", - val: 25 - }, + // { + // key: "COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT", //this component type is deprecated? + // val: 25 + // }, { key: "COMPONENT_TYPE_WEIGHT", val: 26 diff --git a/src/bin/BinComponents.tsx b/src/bin/BinComponents.tsx index 33a912a..f99e349 100644 --- a/src/bin/BinComponents.tsx +++ b/src/bin/BinComponents.tsx @@ -414,7 +414,7 @@ export default function BinComponents(props: Props) { )} - {comp.name()} + {comp.name() + " " + comp.addressDescription(devMap.get(device)?.settings.product)} {components?.get(comp.key()) !== undefined ? ( diff --git a/src/device/DeviceWizard.tsx b/src/device/DeviceWizard.tsx index d426c21..4de3cc2 100644 --- a/src/device/DeviceWizard.tsx +++ b/src/device/DeviceWizard.tsx @@ -26,7 +26,8 @@ import { import { GetDeviceProductIcon, GetDeviceProductLabel } from "products/DeviceProduct"; import { pond } from "protobuf-ts/pond"; import { quack } from "protobuf-ts/quack"; -import { useComponentAPI, useGlobalState, useSnackbar } from "providers"; +import { useComponentAPI, useDeviceAPI, useGlobalState, useSnackbar } from "providers"; + import React, { useState } from "react"; import DeviceSVG, { PortInformation } from "./deviceSVG"; import { makeStyles } from "@mui/styles"; @@ -83,6 +84,8 @@ export default function DeviceWizard(props: Props) { ); const classes = useStyles(); const [selectedPort, setSelectedPort] = useState(); + const deviceAPI = useDeviceAPI() + const { openSnack } = useSnackbar() //const [addressType, setAddressType] = useState(quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY); const wizardMenu = () => { @@ -118,6 +121,22 @@ export default function DeviceWizard(props: Props) { )} + {selectedPort && selectedPort.addressType === quack.AddressType.ADDRESS_TYPE_I2C && device.featureSupported("detectI2C") && ( + + { + deviceAPI.detectI2C(device.id()) + .then(resp => { + openSnack("Device will scan port on next check-in") + }).catch(err => { + openSnack("Command failed to send to device") + }) + }}> + Scan Port + + + )} {portComponents.length > 0 && ( Current Components diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx new file mode 100644 index 0000000..e706da0 --- /dev/null +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -0,0 +1,93 @@ +import { Box, Card, DialogContent, FormControlLabel, Radio, RadioGroup, Step, StepLabel, Stepper } from "@mui/material"; +import { cloneDeep } from "lodash"; +import { getSubtypes, Subtype } from "pbHelpers/ComponentType"; +import { pond, quack } from "protobuf-ts/pond"; +import React from "react"; +import { useEffect, useState } from "react"; +import ScannedI2C from "./ScannedI2C"; +import ComponentForm from "component/ComponentForm"; +import { Component, Device } from "models"; + +interface Props { + scannedComponents: pond.ComponentAddressMap + device: Device +} + +interface CompStep { + label: string; + completed?: boolean; +} + +export default function DeviceScannedComponents(props: Props){ + const {scannedComponents, device} = props + const [scannedI2C, setScannedI2C] = useState() + const [components, setComponents] = useState([]) + const [steps, setSteps] = useState([]); + const [currentStep, setCurrentStep] = useState(0) + const [settingsValid, setSettingsValid] = useState(false); + + useEffect(()=>{ + if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) + },[scannedComponents]) + + useEffect(() => { + let steps: CompStep[] = [] + components.forEach(comp => { + steps.push({ + label: comp.name(), + completed: false + }) + }) + },[components]) + + const stepper = () => { + return ( + + {steps.map(compStep => { + const labelProps: { + optional?: React.ReactNode; + } = {}; + return ( + + {compStep.label} + + ); + })} + + ); + }; + + const addComponentContent = () => { + return ( + + {stepper()} + { + components[currentStep].settings = component.settings; + setSettingsValid(isValid); + }} + /> + + ); + }; + + + + return ( + + {scannedI2C && + + I2C Components Found + {scannedI2C?.settings?.foundAddresses.map((addr, index) => { + return ( + {}} /> + ) + })} + + } + + ) +} \ No newline at end of file diff --git a/src/device/autoDetect/ScannedI2C.tsx b/src/device/autoDetect/ScannedI2C.tsx new file mode 100644 index 0000000..ff057d4 --- /dev/null +++ b/src/device/autoDetect/ScannedI2C.tsx @@ -0,0 +1,107 @@ +import { Box, Button, FormControlLabel, MenuItem, Radio, RadioGroup, TextField } from "@mui/material"; +import { getAddressTypes, getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType"; +import { GetProductAvailability } from "products/DeviceProduct"; +import { pond } from "protobuf-ts/pond"; +import { quack } from "protobuf-ts/quack"; +import { useEffect, useState } from "react"; + +interface Props { + decimalAddress: number + deviceProduct: pond.DeviceProduct + updateComponentList: () => void +} + +export default function ScannedI2C(props: Props){ + const {decimalAddress, deviceProduct} = props + const [types, setTypes] = useState([]) + const [subtypeOptions, setSubtypeOptions] = useState>([]) + const [selectedType, setSelectedType] = useState(quack.ComponentType.COMPONENT_TYPE_INVALID) + const [selectedSubtype, setSelectedSubtype] = useState(0) + + useEffect(()=>{ + //convert the address to hex + let hexAddress = parseInt(decimalAddress.toString(16)) + hexAddress = 0x2a //hardcoding for testing + let types: quack.ComponentType[] = [] + //find what component types use that address + let productAvailability = GetProductAvailability(deviceProduct) + if(productAvailability){ + let i2cMap = productAvailability.get(quack.AddressType.ADDRESS_TYPE_I2C) + if(i2cMap){ + i2cMap.forEach((val, key) => { + let addresses = val as number[] ?? [] + if(addresses.length > 0 && addresses.includes(hexAddress)){ + types.push(key) + } + }) + } + } + //this if can be taken out if we dont want to select the first component type by default + if(types.length > 0) { + setSelectedType(types[0]) + buildSubtypeOptions(types[0]) + } + setTypes(types) + },[decimalAddress, deviceProduct]) + + const buildSubtypeOptions = (compType: quack.ComponentType) => { + let subtypes = getSubtypes(compType) + let validSub: Subtype[] = [] + //have to exclude subtypes that are not I2C + subtypes.forEach((sub,i) => { + let addrTypes = getAddressTypes(compType, sub.key) + if (addrTypes.includes(quack.AddressType.ADDRESS_TYPE_I2C)){ + validSub.push(sub) + } + }) + //set the selected on to be the first in the valid selection + if(validSub.length > 0){ + setSelectedSubtype(validSub[0].key) + } + setSubtypeOptions(validSub) + } + + + + return ( + + Sensor 1 + { + console.log(value) + let v = parseInt(value) + if (!isNaN(v)){ + buildSubtypeOptions(v) + } + }}> + {types.map((type, i) => { + return ( + } + label={getFriendlyName(type)} + /> + ) + })} + + {subtypeOptions.length > 0 && + { + let val = +event.target.value + console.log(event.target.value) + setSelectedSubtype(val) + }} + select> + {subtypeOptions.map(s => ( + {s.friendlyName} + ))} + + } + + + ) +} \ No newline at end of file diff --git a/src/models/Component.ts b/src/models/Component.ts index c9bbc2c..84f5574 100644 --- a/src/models/Component.ts +++ b/src/models/Component.ts @@ -3,6 +3,7 @@ import { quack } from "protobuf-ts/pond"; import { or } from "utils/types"; import { cloneDeep } from "lodash"; import { getSubtypes } from "pbHelpers/ComponentType"; +import { getFriendlyAddressTypeName, getHumanReadableAddress } from "pbHelpers/AddressType"; // import { getSubtypes } from "pbHelpers/ComponentType"; export class Component { @@ -105,4 +106,33 @@ export class Component { } return 0; } + + public addressDescription = (deviceProduct?: pond.DeviceProduct) => { + if ( + this.settings.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY || + (this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100) + ) { + let addressDescription = getHumanReadableAddress( + this.settings.addressType, + this.settings.type, + this.settings.address, + deviceProduct + ); + if (addressDescription === "") { + addressDescription = "Internal"; + } + let port = "Port: " + addressDescription; + let cableID = ""; + if ( + this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100 + ) { + cableID = "Cable: " + (this.settings.addressType - 8); + } + return port + " " + cableID; + } else { + return getFriendlyAddressTypeName(this.settings.addressType); + } + }; } diff --git a/src/models/Device.ts b/src/models/Device.ts index b201407..6311981 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -33,6 +33,21 @@ const featureVersions: Map = new Map([ v2CellBlue: "2.0.44", v2EthBlue: "2.0.44" } + ],[ + "detectI2C", + { + photon: "NA", + electron: "NA", + v2Wifi: "2.1.6", + v2Cell: "2.1.6", + v2WifiS3: "2.1.6", + v2CellS3: "2.1.6", + v2CellBlack: "2.1.6", + v2CellGreen: "2.1.6", + v2WifiBlue: "2.1.6", + v2CellBlue: "2.1.6", + v2EthBlue: "2.1.6" + } ] ]); export class Device { diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index e50469b..6b36115 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -1,4 +1,4 @@ -import { Button, Divider, List, ListItem, Typography } from "@mui/material"; +import { Button, Card, Divider, List, ListItem, Typography } from "@mui/material"; import Grid from '@mui/material/Grid2'; import { Component, Device, Interaction, User } from "models"; import { getContextKeys, getContextTypes } from "pbHelpers/Context"; @@ -20,6 +20,7 @@ import { isController } from "pbHelpers/ComponentType"; import { or } from "utils"; import ComponentDiagnostics from "component/ComponentDiagnostics"; import DeviceWizard from "device/DeviceWizard"; +import DeviceScannedComponents from "device/autoDetect/DeviceScannedComponents"; export interface DevicePageData { device: Device; @@ -56,6 +57,7 @@ export default function DevicePage() { const [components, setComponents] = useState>(new Map()); const [diagnosticComponents, setDiagnosticComponents] = useState([]); + const [scannedAddresses, setScannedAddresses] = useState(undefined) // const [components, setComponents] = useState([]); const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false) @@ -162,8 +164,19 @@ export default function DevicePage() { .finally(() => setLoading(false)); } + const loadPortScan = () => { + deviceAPI.listFoundComponents(device.id()) + .then(resp => { + setScannedAddresses(resp.data.foundComponents ?? undefined) + }) + .catch(err => { + console.log(err) + }) + } + useEffect(() => { loadDevice() + loadPortScan() }, [deviceID, as]) const toggleNotificationPreference = () => { @@ -404,7 +417,7 @@ export default function DevicePage() { ) : ( <> - + - - + {scannedAddresses && + + + + } + {diagnosticComponents.length > 0 && + + {diagnosticComponents.map(comp => ( - + + } )} diff --git a/src/pbHelpers/AddressTypes/I2C.ts b/src/pbHelpers/AddressTypes/I2C.ts index 7012eee..c17c743 100644 --- a/src/pbHelpers/AddressTypes/I2C.ts +++ b/src/pbHelpers/AddressTypes/I2C.ts @@ -12,7 +12,7 @@ export const I2C: AddressTypeExtension = { [quack.ComponentType.COMPONENT_TYPE_STEPPER_MOTOR, 0x13], [quack.ComponentType.COMPONENT_TYPE_PH, 0x3f], [quack.ComponentType.COMPONENT_TYPE_DHT, 0x3f], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, 0x3f], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, 0x3f], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_CAPACITANCE, 0x4f], [quack.ComponentType.COMPONENT_TYPE_CAPACITOR_CABLE, 0x4f], [quack.ComponentType.COMPONENT_TYPE_SEN5X, 0x68], diff --git a/src/pbHelpers/DeviceAvailability.ts b/src/pbHelpers/DeviceAvailability.ts index 84cfa7e..c50a2a4 100644 --- a/src/pbHelpers/DeviceAvailability.ts +++ b/src/pbHelpers/DeviceAvailability.ts @@ -54,7 +54,7 @@ const DefaultAvailability: DeviceAvailabilityMap = new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -48,7 +48,7 @@ export const BindaptPlusModAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -78,10 +78,11 @@ export const BindaptPlusProAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], - [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] + [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]], + [quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x2a]] ]) ], [quack.AddressType.ADDRESS_TYPE_POWER, [0]], @@ -109,7 +110,7 @@ export const BindaptPlusProModAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -136,7 +137,7 @@ export const BindaptPlusLiteAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -192,7 +193,7 @@ export const BindaptUltimateAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -219,7 +220,7 @@ export const BinMonitorAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]] ]) @@ -248,7 +249,7 @@ export const BindaptV2MonitorAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -280,7 +281,7 @@ export const BindaptV2AutomateAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] diff --git a/src/products/DeviceProduct.ts b/src/products/DeviceProduct.ts index 792be79..844e0be 100644 --- a/src/products/DeviceProduct.ts +++ b/src/products/DeviceProduct.ts @@ -64,7 +64,7 @@ const Weather: DeviceProductDescriber = { new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]] ]) ], diff --git a/src/products/Nexus/NexusAvailability.ts b/src/products/Nexus/NexusAvailability.ts index 9f9fc57..2a1cf51 100644 --- a/src/products/Nexus/NexusAvailability.ts +++ b/src/products/Nexus/NexusAvailability.ts @@ -20,7 +20,7 @@ export const NexusSTAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] ]) diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 7b7384c..f42133f 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -23,7 +23,7 @@ export interface IDeviceAPIContext { ) => Promise>; getMulti: (ids: number[] | string[], otherTeam?: string) => Promise>; detectI2C: (id: number, otherTeam?: string) => Promise>; - listFoundComponents: (is: number, otherTeam?: string) => Promise> + listFoundComponents: (id: number, otherTeam?: string) => Promise> getGeoJson: (id: number | string, demo?: boolean, otherTeam?: string) => Promise; getMultiGeoJson: (ids: number[] | string[], otherTeam?: string) => Promise; list: ( From d9483282c84008a904b91b54b819285856d6a326 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:20:43 -0600 Subject: [PATCH 05/11] removed the airflow address for bindat plus since its was only for testing --- src/products/Bindapt/BindaptAvailability.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/products/Bindapt/BindaptAvailability.ts b/src/products/Bindapt/BindaptAvailability.ts index ddcba27..3f70a11 100644 --- a/src/products/Bindapt/BindaptAvailability.ts +++ b/src/products/Bindapt/BindaptAvailability.ts @@ -81,8 +81,7 @@ export const BindaptPlusProAvailability: DeviceAvailabilityMap = new Map< // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], - [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]], - [quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x2a]] + [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] ]) ], [quack.AddressType.ADDRESS_TYPE_POWER, [0]], From a4b6179b2628b56ee952cbfa8d1bfbb66d14f4aa Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:22:29 -0600 Subject: [PATCH 06/11] added function so the component can display its port and cable id --- src/models/Component.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/models/Component.ts b/src/models/Component.ts index c9bbc2c..97b54ba 100644 --- a/src/models/Component.ts +++ b/src/models/Component.ts @@ -3,6 +3,7 @@ import { quack } from "protobuf-ts/pond"; import { or } from "utils/types"; import { cloneDeep } from "lodash"; import { getSubtypes } from "pbHelpers/ComponentType"; +import { getFriendlyAddressTypeName, getHumanReadableAddress } from "pbHelpers/AddressType"; // import { getSubtypes } from "pbHelpers/ComponentType"; export class Component { @@ -105,4 +106,33 @@ export class Component { } return 0; } + + public addressDescription = (deviceProduct?: pond.DeviceProduct) => { + if ( + this.settings.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY || + (this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100) + ) { + let addressDescription = getHumanReadableAddress( + this.settings.addressType, + this.settings.type, + this.settings.address, + deviceProduct + ); + if (addressDescription === "") { + addressDescription = "Internal"; + } + let port = "Port: " + addressDescription; + let cableID = ""; + if ( + this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100 + ) { + cableID = "Cable: " + (this.settings.addressType - 8); + } + return port + " " + cableID; + } else { + return getFriendlyAddressTypeName(this.settings.addressType); + } + }; } From 6ea08107a5ef9d3a6873f915a2870aa8074ad4f2 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:28:37 -0600 Subject: [PATCH 07/11] display port info in the bin components screen --- src/bin/BinComponents.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/BinComponents.tsx b/src/bin/BinComponents.tsx index 33a912a..7864c46 100644 --- a/src/bin/BinComponents.tsx +++ b/src/bin/BinComponents.tsx @@ -414,7 +414,7 @@ export default function BinComponents(props: Props) { )} - {comp.name()} + {comp.name() + " - " + comp.addressDescription(devMap.get(device)?.settings.product)} {components?.get(comp.key()) !== undefined ? ( From 6f12f6818b282c34804264e029beb555057e3ea6 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:30:56 -0600 Subject: [PATCH 08/11] proto update --- package-lock.json | 50 ----------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 456c54d..9aaa021 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7618,15 +7618,6 @@ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, - "node_modules/decode-uri-component": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", - "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", - "license": "MIT", - "engines": { - "node": ">=14.16" - } - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -8414,18 +8405,6 @@ "node": ">=8" } }, - "node_modules/filter-obj": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", - "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -10947,23 +10926,6 @@ "node": ">=6" } }, - "node_modules/query-string": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.2.1.tgz", - "integrity": "sha512-3jTGGLRzlhu/1ws2zlr4Q+GVMLCQTLFOj8CMX5x44cdZG9FQE07x2mQhaNxaKVPNmIDu0mvJ/cEwtY7Pim7hqA==", - "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.4.1", - "filter-obj": "^5.1.0", - "split-on-first": "^3.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -12341,18 +12303,6 @@ "resolved": "https://registry.npmjs.org/splaytree-ts/-/splaytree-ts-1.0.2.tgz", "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==" }, - "node_modules/split-on-first": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", - "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", From eebb2407f484da44f70fe4ab7e6515dceabad452 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 26 Jun 2025 13:31:58 -0600 Subject: [PATCH 09/11] install query-string...again --- package-lock.json | 51 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 52 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9aaa021..04a9cb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#i2c_detect", + "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", "react-color": "^2.19.3", @@ -7618,6 +7619,15 @@ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -8405,6 +8415,18 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -10926,6 +10948,23 @@ "node": ">=6" } }, + "node_modules/query-string": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.2.1.tgz", + "integrity": "sha512-3jTGGLRzlhu/1ws2zlr4Q+GVMLCQTLFOj8CMX5x44cdZG9FQE07x2mQhaNxaKVPNmIDu0mvJ/cEwtY7Pim7hqA==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -12303,6 +12342,18 @@ "resolved": "https://registry.npmjs.org/splaytree-ts/-/splaytree-ts-1.0.2.tgz", "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==" }, + "node_modules/split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/package.json b/package.json index 3287909..99939e6 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#i2c_detect", + "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", "react-color": "^2.19.3", From c8105ef62486ccbb6aaa01bc406146710698a160 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Fri, 27 Jun 2025 14:19:55 -0600 Subject: [PATCH 10/11] finished the card to detect i2c components and select ones to add --- src/component/ComponentSettings.tsx | 2 + .../autoDetect/DeviceScannedComponents.tsx | 163 +++++++++++++++--- src/device/autoDetect/ScannedI2C.tsx | 128 +++++++++----- src/pages/Device.tsx | 11 +- 4 files changed, 232 insertions(+), 72 deletions(-) diff --git a/src/component/ComponentSettings.tsx b/src/component/ComponentSettings.tsx index d762ee3..54653a2 100644 --- a/src/component/ComponentSettings.tsx +++ b/src/component/ComponentSettings.tsx @@ -238,6 +238,7 @@ export default function ComponentSettings(props: Props) { componentType: quack.ComponentType ): number[] => { let positions = availablePositions.get(addressType); + console.log(positions) if (!positions) return []; switch (addressType) { case quack.AddressType.ADDRESS_TYPE_I2C: @@ -412,6 +413,7 @@ export default function ComponentSettings(props: Props) { for (let i = 0; i < addressTypes.length; i++) { let addressType = addressTypes[i]; let availablePositions = getAvailablePositions(addressType, type); + console.log(availablePositions) availableMenuItemPositions.push( diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index e706da0..e07dd94 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -1,4 +1,4 @@ -import { Box, Card, DialogContent, FormControlLabel, Radio, RadioGroup, Step, StepLabel, Stepper } from "@mui/material"; +import { Box, Button, Card, DialogActions, DialogContent, DialogTitle, FormControlLabel, Grid2, Radio, RadioGroup, Step, StepLabel, Stepper, Typography } from "@mui/material"; import { cloneDeep } from "lodash"; import { getSubtypes, Subtype } from "pbHelpers/ComponentType"; import { pond, quack } from "protobuf-ts/pond"; @@ -7,10 +7,16 @@ import { useEffect, useState } from "react"; import ScannedI2C from "./ScannedI2C"; import ComponentForm from "component/ComponentForm"; import { Component, Device } from "models"; +import { DeviceAvailabilityMap, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability"; +import ResponsiveDialog from "common/ResponsiveDialog"; +import { useComponentAPI, useSnackbar } from "hooks"; interface Props { scannedComponents: pond.ComponentAddressMap device: Device + availablePositions: DeviceAvailabilityMap + availableOffsets: OffsetAvailabilityMap + refreshCallback: () => void } interface CompStep { @@ -19,12 +25,15 @@ interface CompStep { } export default function DeviceScannedComponents(props: Props){ - const {scannedComponents, device} = props + const {scannedComponents, device, availablePositions, availableOffsets, refreshCallback} = props + const compAPI = useComponentAPI(); const [scannedI2C, setScannedI2C] = useState() const [components, setComponents] = useState([]) const [steps, setSteps] = useState([]); + const { error, success } = useSnackbar(); const [currentStep, setCurrentStep] = useState(0) const [settingsValid, setSettingsValid] = useState(false); + const [openDialog, setOpenDialog] = useState(false); useEffect(()=>{ if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) @@ -38,6 +47,7 @@ export default function DeviceScannedComponents(props: Props){ completed: false }) }) + setSteps(steps) },[components]) const stepper = () => { @@ -57,37 +67,136 @@ export default function DeviceScannedComponents(props: Props){ ); }; - const addComponentContent = () => { + const addComponents = () => { + let c: pond.MultiComponentSettings = pond.MultiComponentSettings.create(); + components.forEach(component => { + c.components.push(component.settings); + }); + compAPI + .addMultiComponents(device.id(), c) + .then(resp => { + success("Components added to Device"); + }) + .catch(err => { + error("One or more component failed to add"); + }) + .finally(() => { + refreshCallback(); + }); + }; + + const addComponentDialog = () => { return ( - - {stepper()} - { - components[currentStep].settings = component.settings; - setSettingsValid(isValid); - }} - /> - + {setOpenDialog(false)}}> + Adding Components + + {stepper()} + { + components[currentStep].settings = component.settings; + setSettingsValid(isValid); + }} + /> + + + + + + + + {currentStep !== 0 && ( + + )} + {currentStep !== steps.length - 1 && ( + + + + )} + + + + + ); }; + const componentSelection = (newComponent: Component, checked: boolean) => { + let cloneList = cloneDeep(components) + if(checked){ + //add the component to the list + cloneList.push(newComponent) + }else{ + //remove any components that match the component location: (type)-(addressType)-(address) + components.forEach((comp, i) => { + //check the components location against the one in the list + if(comp.locationString() === newComponent.locationString()){ + cloneList.splice(i, 1) + } + }) + } + setComponents(cloneList) + } + return ( - - {scannedI2C && - - I2C Components Found - {scannedI2C?.settings?.foundAddresses.map((addr, index) => { - return ( - {}} /> - ) - })} - - } - + + + {scannedI2C !== undefined && + + + + I2C Components Found + + + {scannedI2C?.settings?.foundAddresses.map((addr, index) => { + return ( + + ) + })} + + } + + + + + {addComponentDialog()} + ) } \ No newline at end of file diff --git a/src/device/autoDetect/ScannedI2C.tsx b/src/device/autoDetect/ScannedI2C.tsx index ff057d4..5b83d44 100644 --- a/src/device/autoDetect/ScannedI2C.tsx +++ b/src/device/autoDetect/ScannedI2C.tsx @@ -1,5 +1,7 @@ -import { Box, Button, FormControlLabel, MenuItem, Radio, RadioGroup, TextField } from "@mui/material"; +import { Box, Button, Checkbox, FormControlLabel, Grid2, MenuItem, Radio, RadioGroup, TextField, Tooltip } from "@mui/material"; +import { Component } from "models"; import { getAddressTypes, getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType"; +import { ComponentAvailabilityMap, DevicePositions } from "pbHelpers/DeviceAvailability"; import { GetProductAvailability } from "products/DeviceProduct"; import { pond } from "protobuf-ts/pond"; import { quack } from "protobuf-ts/quack"; @@ -8,29 +10,29 @@ import { useEffect, useState } from "react"; interface Props { decimalAddress: number deviceProduct: pond.DeviceProduct - updateComponentList: () => void + componentSelectionCallback: (component: Component, checked: boolean) => void + availablePositions: DevicePositions } export default function ScannedI2C(props: Props){ - const {decimalAddress, deviceProduct} = props + const {decimalAddress, deviceProduct, componentSelectionCallback, availablePositions} = props const [types, setTypes] = useState([]) const [subtypeOptions, setSubtypeOptions] = useState>([]) const [selectedType, setSelectedType] = useState(quack.ComponentType.COMPONENT_TYPE_INVALID) const [selectedSubtype, setSelectedSubtype] = useState(0) + const [addressInUse, setAddressInUse] = useState(false) useEffect(()=>{ - //convert the address to hex - let hexAddress = parseInt(decimalAddress.toString(16)) - hexAddress = 0x2a //hardcoding for testing let types: quack.ComponentType[] = [] - //find what component types use that address + //find what component types use that address, this is different than the available positions passed in + //this is meant to get all possibilities according to product type and the given address, availablePositions is the restriction of what is available let productAvailability = GetProductAvailability(deviceProduct) if(productAvailability){ let i2cMap = productAvailability.get(quack.AddressType.ADDRESS_TYPE_I2C) if(i2cMap){ i2cMap.forEach((val, key) => { let addresses = val as number[] ?? [] - if(addresses.length > 0 && addresses.includes(hexAddress)){ + if(addresses.length > 0 && addresses.includes(decimalAddress)){ types.push(key) } }) @@ -40,6 +42,7 @@ export default function ScannedI2C(props: Props){ if(types.length > 0) { setSelectedType(types[0]) buildSubtypeOptions(types[0]) + checkAddressAvailable(types[0]) } setTypes(types) },[decimalAddress, deviceProduct]) @@ -61,47 +64,86 @@ export default function ScannedI2C(props: Props){ setSubtypeOptions(validSub) } + const checkAddressAvailable = (compType: quack.ComponentType) => { + let i2cMap = availablePositions as ComponentAvailabilityMap + let compAddresses = i2cMap.get(compType) ?? [] + if (!compAddresses.includes(decimalAddress)){ + setAddressInUse(true) + }else{ + setAddressInUse(false) + } + } + + + + const componentSelected = (event: React.ChangeEvent, checked: boolean) => { + //build a component with given information and defaults for the rest + let component = Component.create() + component.settings.type = selectedType + component.settings.subtype = selectedSubtype + component.settings.addressType = quack.AddressType.ADDRESS_TYPE_I2C + component.settings.address = decimalAddress + component.settings.name = getFriendlyName(selectedType, selectedSubtype) + //return the component and the checked status to the parent + componentSelectionCallback(component, checked) + } return ( Sensor 1 - { - console.log(value) - let v = parseInt(value) - if (!isNaN(v)){ - buildSubtypeOptions(v) - } - }}> - {types.map((type, i) => { - return ( - } - label={getFriendlyName(type)} + + + { + let v = parseInt(value) + if (!isNaN(v)){ + buildSubtypeOptions(v) + checkAddressAvailable(v) + } + }}> + {types.map((type, i) => { + return ( + } + label={getFriendlyName(type)} + /> + ) + })} + + + + {subtypeOptions.length > 0 && + { + let val = +event.target.value + setSelectedSubtype(val) + }} + select> + {subtypeOptions.map(s => ( + {s.friendlyName} + ))} + + } + + + - ) - })} - - {subtypeOptions.length > 0 && - { - let val = +event.target.value - console.log(event.target.value) - setSelectedSubtype(val) - }} - select> - {subtypeOptions.map(s => ( - {s.friendlyName} - ))} - - } - + } + /> + + + ) } \ No newline at end of file diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index 6b36115..6a769c0 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -167,7 +167,9 @@ export default function DevicePage() { const loadPortScan = () => { deviceAPI.listFoundComponents(device.id()) .then(resp => { - setScannedAddresses(resp.data.foundComponents ?? undefined) + if (resp.data.foundComponents?.i2c){ + setScannedAddresses(resp.data.foundComponents ?? undefined) + } }) .catch(err => { console.log(err) @@ -427,7 +429,12 @@ export default function DevicePage() { {scannedAddresses && - + } {diagnosticComponents.length > 0 && From ba7852bbc7ae803d6f3977819f5294ddff8202e2 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 30 Jun 2025 11:34:43 -0600 Subject: [PATCH 11/11] adding display for when the foundaddresses is an empty array --- .../autoDetect/DeviceScannedComponents.tsx | 127 ++++++++++-------- src/device/autoDetect/ScannedI2C.tsx | 9 +- 2 files changed, 77 insertions(+), 59 deletions(-) diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index e07dd94..52a66e4 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -37,6 +37,14 @@ export default function DeviceScannedComponents(props: Props){ useEffect(()=>{ if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) + //makes the array empty for testing + // if (scannedComponents.i2c) { + // let clone = cloneDeep(scannedComponents.i2c) + // if (clone.settings){ + // clone.settings.foundAddresses = [] + // } + // setScannedI2C(clone) + // } },[scannedComponents]) useEffect(() => { @@ -101,57 +109,56 @@ export default function DeviceScannedComponents(props: Props){ }} /> - - - - - - - {currentStep !== 0 && ( - - )} - {currentStep !== steps.length - 1 && ( - - - - )} - - - - + + + + + + + {currentStep !== 0 && ( + + )} + {currentStep !== steps.length - 1 && ( + + + + )} + + + + ); }; @@ -182,14 +189,24 @@ export default function DeviceScannedComponents(props: Props){ - I2C Components Found + I2C Sensors - {scannedI2C?.settings?.foundAddresses.map((addr, index) => { + {scannedI2C.settings?.foundAddresses && scannedI2C.settings.foundAddresses.length > 0 ? scannedI2C?.settings?.foundAddresses.map((addr, index) => { return ( - + ) - })} + }) : + + + No Sensors Found + + + } } diff --git a/src/device/autoDetect/ScannedI2C.tsx b/src/device/autoDetect/ScannedI2C.tsx index 5b83d44..db5954a 100644 --- a/src/device/autoDetect/ScannedI2C.tsx +++ b/src/device/autoDetect/ScannedI2C.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Checkbox, FormControlLabel, Grid2, MenuItem, Radio, RadioGroup, TextField, Tooltip } from "@mui/material"; +import { Box, Button, Checkbox, FormControlLabel, Grid2, MenuItem, Radio, RadioGroup, TextField, Tooltip, Typography } from "@mui/material"; import { Component } from "models"; import { getAddressTypes, getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType"; import { ComponentAvailabilityMap, DevicePositions } from "pbHelpers/DeviceAvailability"; @@ -12,10 +12,11 @@ interface Props { deviceProduct: pond.DeviceProduct componentSelectionCallback: (component: Component, checked: boolean) => void availablePositions: DevicePositions + sensorNum?: number } export default function ScannedI2C(props: Props){ - const {decimalAddress, deviceProduct, componentSelectionCallback, availablePositions} = props + const {decimalAddress, deviceProduct, componentSelectionCallback, availablePositions, sensorNum} = props const [types, setTypes] = useState([]) const [subtypeOptions, setSubtypeOptions] = useState>([]) const [selectedType, setSelectedType] = useState(quack.ComponentType.COMPONENT_TYPE_INVALID) @@ -90,8 +91,8 @@ export default function ScannedI2C(props: Props){ return ( - - Sensor 1 + + {sensorNum && Sensor {sensorNum}}