Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add support for battery slots #138

Merged
merged 2 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/appReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NrfConnectState } from '@nordicsemiconductor/pc-nrfconnect-shared';
import { combineReducers } from 'redux';

import confirmBeforeCloseReducer from './features/confirmBeforeClose/confirmBeforeCloseSlice';
import downloadBatteryModelSlice from './features/pmicControl/downloadBatteryModelSlice';
import pmicControlReducer from './features/pmicControl/pmicControlSlice';
import profilingProjectsReducer from './features/pmicControl/profilingProjectsSlice.';
import profilingReducer from './features/pmicControl/profilingSlice';
Expand All @@ -24,6 +25,7 @@ const appReducer = combineReducers({
profiling: profilingReducer,
pmicControl: pmicControlReducer,
serial: serialReducer,
downloadBatteryModel: downloadBatteryModelSlice,
});

export default appReducer;
42 changes: 13 additions & 29 deletions src/components/FuelGauge/FuelGaugeSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@nordicsemiconductor/pc-nrfconnect-shared';

import { getProfileBuffer } from '../../actions/fileActions';
import { showDialog } from '../../features/pmicControl/downloadBatteryModelSlice';
import { DocumentationTooltip } from '../../features/pmicControl/npm/documentation/documentation';
import {
dialogHandler,
Expand All @@ -29,7 +30,6 @@ import {
getStoredBatterModels,
} from '../../features/pmicControl/pmicControlSlice';
import { setProfilingStage } from '../../features/pmicControl/profilingSlice';
import { writeBatterModel } from '../Profiling/helpers';

export default ({ disabled }: { disabled: boolean }) => {
const dispatch = useDispatch();
Expand All @@ -54,35 +54,23 @@ export default ({ disabled }: { disabled: boolean }) => {

const batteryModelItems: DropdownItem[] = useMemo(() => {
const items = [...hardcodedBatterModels];
if (activeBatteryModel) {
if (
hardcodedBatterModels.filter(
v => v && v.name !== activeBatteryModel.name
).length > 0
)
items.push(activeBatteryModel);
}

storedBatterModels?.forEach(storedBatterModel => {
if (storedBatterModel) items.push(storedBatterModel);
});

const keys = new Set(items.map(item => item.name));
return Array.from(keys).map(key => ({
label: `${key} (${
getClosest(
items.find(batterModel => batterModel.name === key),
latestAdcSample?.tBat ?? 24
)?.capacity ?? ''
return items.map(batterModel => ({
label: `${
batterModel?.slotIndex != null
? `#${batterModel?.slotIndex} `
: ''
}${batterModel.name} (${
getClosest(batterModel, latestAdcSample?.tBat ?? 24)
?.capacity ?? ''
} mAh)`,
value: key,
value: batterModel.name,
}));
}, [
activeBatteryModel,
hardcodedBatterModels,
latestAdcSample?.tBat,
storedBatterModels,
]);
}, [hardcodedBatterModels, latestAdcSample?.tBat, storedBatterModels]);

const selectedActiveItemBatteryMode = useMemo(
() =>
Expand Down Expand Up @@ -112,7 +100,7 @@ export default ({ disabled }: { disabled: boolean }) => {
npmDevice?.setActiveBatteryModel(item.value);
}}
selectedItem={selectedActiveItemBatteryMode}
disabled={disabled}
disabled={disabled || batteryModelItems.length === 0}
/>
<DocumentationTooltip
placement="right-start"
Expand All @@ -125,11 +113,7 @@ export default ({ disabled }: { disabled: boolean }) => {
onClick={() => {
getProfileBuffer()
.then(buffer => {
if (npmDevice) {
dispatch(
writeBatterModel(buffer, npmDevice)
);
}
dispatch(showDialog(buffer));
})
.catch(res => {
dispatch(
Expand Down
96 changes: 96 additions & 0 deletions src/components/FuelGauge/SlotSelectionDownloadDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2015 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
*/

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
DialogButton,
Dropdown,
DropdownItem,
GenericDialog,
} from '@nordicsemiconductor/pc-nrfconnect-shared';

import {
closeDialog,
getBuffer,
getShowDialog,
} from '../../features/pmicControl/downloadBatteryModelSlice';
import {
getNpmDevice,
getStoredBatterModels,
} from '../../features/pmicControl/pmicControlSlice';

export default () => {
const dispatch = useDispatch();
const npmDevice = useSelector(getNpmDevice);
const storedBatterModels = useSelector(getStoredBatterModels);
const [slot, setSlot] = useState(0);
const buffer = useSelector(getBuffer);
const showDialog = useSelector(getShowDialog);

const items: DropdownItem<number>[] = [];

for (
let i = 0;
i < (npmDevice?.getNumberOfBatteryModelSlots() ?? 0);
i += 1
) {
const module = storedBatterModels?.find(m => m.slotIndex === i);

items.push({
value: i,
label: `Slot ${i}: ${module?.name ?? 'Empty'}`,
});
}

console.log(items);

return showDialog ? (
<GenericDialog
title="Write battery model"
footer={
<>
<DialogButton
onClick={() => {
dispatch(closeDialog());
if (npmDevice && buffer) {
npmDevice.downloadFuelGaugeProfile(
buffer,
slot
);
}
}}
variant="primary"
>
Write
</DialogButton>
<DialogButton
onClick={() => {
dispatch(closeDialog());
}}
variant="secondary"
>
Cancel
</DialogButton>
</>
}
isVisible
>
<div>
{`Writing battery profile will reset the current fuel gauge and
overwrite the model in the slot. Click 'Write' to continue.`}
</div>
<Dropdown
label="Programming slot"
items={items}
onSelect={item => {
setSlot(item.value);
}}
selectedItem={items[slot]}
/>
</GenericDialog>
) : null;
};
4 changes: 3 additions & 1 deletion src/components/Profiling/Dialog/ConfigurationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ export default ({ isVisible }: { isVisible: boolean }) => {
setName(event.target.value);
const match =
event.target.value.match(/^[a-zA-Z0-9]+$/);
setValidName(!!match);
setValidName(
!!match && event.target.value !== 'default'
);
}}
value={name}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import { useDispatch, useSelector } from 'react-redux';
import { showSaveDialog } from '../../../actions/fileActions';
import { stringToFile } from '../../../features/helpers';
import { generateParamsFromCSV } from '../../../features/nrfutillNpm/csvProcessing';
import { showDialog } from '../../../features/pmicControl/downloadBatteryModelSlice';
import { getNpmDevice } from '../../../features/pmicControl/pmicControlSlice';
import { getProjectProfileProgress } from '../../../features/pmicControl/profilingProjectsSlice.';
import useIsUIDisabled from '../../../features/useIsUIDisabled';
import {
isProfileReadyForProcessing,
readAndUpdateProjectSettings,
writeBatterModel,
} from '../helpers';
import { ProfilingProject } from '../types';
import AddEditProfileDialog from './AddEditProfileDialog';
Expand Down Expand Up @@ -123,10 +123,7 @@ export default ({
onClick={() => {
if (profile.batteryJson && npmDevice) {
dispatch(
writeBatterModel(
Buffer.from(profile.batteryJson),
npmDevice
)
showDialog(Buffer.from(profile.batteryJson))
);
}
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ import {
generateParamsFromCSV,
mergeBatteryParams,
} from '../../../features/nrfutillNpm/csvProcessing';
import { showDialog } from '../../../features/pmicControl/downloadBatteryModelSlice';
import { getNpmDevice } from '../../../features/pmicControl/pmicControlSlice';
import {
getProjectProfileProgress,
removeRecentProject,
} from '../../../features/pmicControl/profilingProjectsSlice.';
import useIsUIDisabled from '../../../features/useIsUIDisabled';
import { isProfileReadyForProcessing, writeBatterModel } from '../helpers';
import { isProfileReadyForProcessing } from '../helpers';
import { ProfilingProject } from '../types';
import AddEditProfileDialog from './AddEditProfileDialog';
import AddEditProjectDialog from './AddEditProjectDialog';
Expand Down Expand Up @@ -181,10 +182,7 @@ export default ({
.then(data => {
if (npmDevice) {
dispatch(
writeBatterModel(
Buffer.from(data.json),
npmDevice
)
showDialog(Buffer.from(data.json))
);
}
setGeneratingBatterModel(false);
Expand Down
25 changes: 1 addition & 24 deletions src/components/Profiling/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ import path from 'path';

import packageJsons from '../../../package.json';
import { RootState } from '../../appReducer';
import {
dialogHandler,
DOWNLOAD_BATTERY_PROFILE_DIALOG_ID,
} from '../../features/pmicControl/npm/pmicHelpers';
import { NpmDevice, Profile } from '../../features/pmicControl/npm/types';
import { Profile } from '../../features/pmicControl/npm/types';
import {
addRecentProject,
loadRecentProject,
Expand Down Expand Up @@ -148,22 +144,3 @@ export const saveProjectSettings =

export const reloadRecentProjects = (): AppThunk => dispatch =>
dispatch(setRecentProjects(loadRecentProject()));

export const writeBatterModel =
(data: Buffer, npmDevice: NpmDevice): AppThunk =>
dispatch => {
dispatch(
dialogHandler({
uuid: DOWNLOAD_BATTERY_PROFILE_DIALOG_ID,
message: `Write battery profile will reset the current fuel gauge. Click 'Write' to continue.`,
confirmLabel: 'Write',
confirmClosesDialog: false,
cancelLabel: 'Cancel',
title: 'Write',
onConfirm: () => {
npmDevice.downloadFuelGaugeProfile(Buffer.from(data));
},
onCancel: () => {},
})
);
};
42 changes: 42 additions & 0 deletions src/features/pmicControl/downloadBatteryModelSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2015 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
*/

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

import type { RootState } from '../../appReducer';

interface DownloadProfileSlice {
showDialog: boolean;
bufferToWite?: Buffer;
}

const initialState: DownloadProfileSlice = {
showDialog: false,
};

const downloadBatteryProfileSlice = createSlice({
name: 'downloadBatteryProfile',
initialState,
reducers: {
closeDialog() {
return {
...initialState,
};
},
showDialog(state, action: PayloadAction<Buffer>) {
state.showDialog = true;
state.bufferToWite = action.payload;
},
},
});

export const getShowDialog = (state: RootState) =>
state.app.downloadBatteryModel.bufferToWite;
export const getBuffer = (state: RootState) =>
state.app.downloadBatteryModel.bufferToWite;

export const { closeDialog, showDialog } = downloadBatteryProfileSlice.actions;
export default downloadBatteryProfileSlice.reducer;
4 changes: 3 additions & 1 deletion src/features/pmicControl/npm/basePmicDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const baseNpmDevice: IBaseNpmDevice = (
noOfLdos?: number;
noOfGPIOs?: number;
noOfLEDs?: number;
noOfBatterySlots?: number;
},
supportsVersion: string
) => {
Expand Down Expand Up @@ -284,7 +285,7 @@ export const baseNpmDevice: IBaseNpmDevice = (
},

onStoredBatteryModelUpdate: (
handler: (payload: (BatteryModel | null)[]) => void
handler: (payload: BatteryModel[]) => void
) => {
eventEmitter.on('onStoredBatteryModelUpdate', handler);
return () => {
Expand Down Expand Up @@ -344,6 +345,7 @@ export const baseNpmDevice: IBaseNpmDevice = (
getNumberOfLdos: () => devices.noOfLdos ?? 0,
getNumberOfGPIOs: () => devices.noOfGPIOs ?? 0,
getNumberOfLEDs: () => devices.noOfLEDs ?? 0,
getNumberOfBatteryModelSlots: () => devices.noOfBatterySlots ?? 0,

isSupportedVersion: () =>
new Promise<{ supported: boolean; version: string }>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,14 @@ export default (
'Battery models stored in database:'
);
if (models.length < 2) {
eventEmitter.emit(
'onStoredBatteryModelUpdate',
undefined
);
eventEmitter.emit('onStoredBatteryModelUpdate', []);
return;
}
const stringModels = models[1].trim().split('\n');
const list = stringModels.map(parseBatteryModel);
eventEmitter.emit(
'onStoredBatteryModelUpdate',
list.length !== 0 ? list : undefined
list.filter(item => item != null)
);
},
noop
Expand Down
Loading
Loading