Skip to content

Commit 828c944

Browse files
committed
feat: Rework scales UI
1 parent 4d4bb6b commit 828c944

37 files changed

+732
-456
lines changed

src/display/plugins/BLEScalePlugin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class BLEScalePlugin : public Plugin {
3535
}
3636
return "";
3737
};
38+
int getRSSI() {
39+
if (scale != nullptr && scale->isConnected()) {
40+
return scale->getRSSI();
41+
}
42+
return 0;
43+
};
3844

3945
std::vector<DiscoveredDevice> getDiscoveredScales() const;
4046
void tare() const;

src/display/plugins/WebUIPlugin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void WebUIPlugin::loop() {
109109
doc["gtv"] = controller->getSettings().getTargetGrindVolume();
110110
doc["gt"] = controller->isVolumetricAvailable() && controller->getSettings().isVolumetricTarget() ? 1 : 0;
111111
doc["gact"] = controller->isGrindActive() ? 1 : 0;
112+
doc["rssi"] = controller->getClientController()->getClient()->getRssi();
112113

113114
bool bleConnected = BLEScales.isConnected();
114115
// Add Bluetooth scale weight information
@@ -666,6 +667,7 @@ void WebUIPlugin::handleBLEScaleList(AsyncWebServerRequest *request) {
666667
JsonDocument scale;
667668
scale["uuid"] = device.getAddress().toString();
668669
scale["name"] = device.getName();
670+
scale["rssi"] = device.getRSSI();
669671
scalesArray.add(scale);
670672
}
671673
AsyncResponseStream *response = request->beginResponseStream("application/json");
@@ -704,6 +706,7 @@ void WebUIPlugin::handleBLEScaleInfo(AsyncWebServerRequest *request) {
704706
doc["connected"] = BLEScales.isConnected();
705707
doc["name"] = BLEScales.getName();
706708
doc["uuid"] = BLEScales.getUUID();
709+
doc["rssi"] = BLEScales.getRSSI();
707710
AsyncResponseStream *response = request->beginResponseStream("application/json");
708711
serializeJson(doc, *response);
709712
request->send(response);

web/src/components/Header.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export function Header() {
137137
onClick={() => openCb(false)}
138138
/>
139139
<HeaderItem
140-
label='Bluetooth Scales'
140+
label='Bluetooth Devices'
141141
link='/scales'
142142
icon={faBluetoothB}
143143
onClick={() => openCb(false)}

web/src/components/Navigation.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function Navigation(props) {
4040
<hr className='h-5 border-0' />
4141
<div className='space-y-1.5'>
4242
<MenuItem label='PID Autotune' link='/pidtune' icon={faTemperatureHalf} />
43-
<MenuItem label='Bluetooth Scales' link='/scales' icon={faBluetoothB} />
43+
<MenuItem label='Bluetooth Devices' link='/scales' icon={faBluetoothB} />
4444
<MenuItem label='Settings' link='/settings' icon={faCog} />
4545
</div>
4646
<hr className='h-5 border-0' />

web/src/index.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ export function App() {
4949
<Route path='/history' component={ShotHistory} />
5050
<Route path='/analyzer' component={ShotAnalyzer} />
5151
<Route path='/statistics' component={StatisticsPage} />
52-
<Route path='/statistics/:sourceAlias/:profileName' component={StatisticsPage} />
52+
<Route
53+
path='/statistics/:sourceAlias/:profileName'
54+
component={StatisticsPage}
55+
/>
5356
<Route path='/analyzer/:source/:id' component={ShotAnalyzer} />{' '}
5457
{/*deep-link route (sorce & ID)*/}
5558
<Route default component={NotFound} />

web/src/pages/OTA/index.jsx

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ApiServiceContext } from '../../services/ApiService.js';
55
import { downloadJson } from '../../utils/download.js';
66
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
77
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
8+
import { machine } from '../../services/ApiService.js';
89

910
const imageUrlToBase64 = async blob => {
1011
return new Promise((onSuccess, onError) => {
@@ -27,6 +28,7 @@ export function OTA() {
2728
const [formData, setFormData] = useState({});
2829
const [phase, setPhase] = useState(0);
2930
const [progress, setProgress] = useState(0);
31+
const rssi = machine.value.status.rssi;
3032

3133
const downloadSupportData = useCallback(async () => {
3234
const settingsResponse = await fetch(`/api/settings`);
@@ -63,15 +65,15 @@ export function OTA() {
6365
apiService.off('evt:ota-progress', listenerId);
6466
};
6567
}, [apiService]);
66-
68+
6769
useEffect(() => {
6870
const listenerId = apiService.on('evt:history-rebuild-progress', msg => {
6971
setRebuildProgress({
7072
total: msg.total || 0,
7173
current: msg.current || 0,
72-
status: msg.status || ''
74+
status: msg.status || '',
7375
});
74-
76+
7577
if (msg.status === 'completed' || msg.status === 'error') {
7678
setRebuilding(false);
7779
setRebuilt(msg.status === 'completed');
@@ -159,7 +161,7 @@ export function OTA() {
159161
<div className='grid grid-cols-1 gap-4 lg:grid-cols-12'>
160162
<Card sm={12} title='System Information'>
161163
<div className='flex flex-col space-y-4'>
162-
<label htmlFor='channel' className='text-sm font-medium'>
164+
<label htmlFor='channel' className='mb-2 block text-sm font-medium'>
163165
Update Channel
164166
</label>
165167
<select id='channel' name='channel' className='select select-bordered w-full'>
@@ -173,15 +175,13 @@ export function OTA() {
173175
</div>
174176

175177
<div className='flex flex-col space-y-4'>
176-
<label className='text-sm font-medium'>Hardware</label>
177-
<div className='input input-bordered bg-base-200 cursor-default break-words whitespace-normal'>
178-
{formData.hardware}
179-
</div>
178+
<label className='mb-2 block text-sm font-medium'>Hardware</label>
179+
<span className='font-light'>{formData.hardware}</span>
180180
</div>
181181

182182
<div className='flex flex-col space-y-4'>
183-
<label className='text-sm font-medium'>Controller Version</label>
184-
<div className='input input-bordered bg-base-200 cursor-default break-words whitespace-normal'>
183+
<label className='mb-2 block text-sm font-medium'>Controller Version</label>
184+
<div className='flex flex-row gap-2 font-light'>
185185
<span className='break-all'>{formData.controllerVersion}</span>
186186
{formData.controllerUpdateAvailable && (
187187
<span className='text-primary font-bold break-all'>
@@ -192,8 +192,8 @@ export function OTA() {
192192
</div>
193193

194194
<div className='flex flex-col space-y-4'>
195-
<label className='text-sm font-medium'>Display Version</label>
196-
<div className='input input-bordered bg-base-200 cursor-default break-words whitespace-normal'>
195+
<label className='mb-2 block text-sm font-medium'>Display Version</label>
196+
<div className='flex flex-row gap-2 font-light'>
197197
<span className='break-all'>{formData.displayVersion}</span>
198198
{formData.displayUpdateAvailable && (
199199
<span className='text-primary font-bold break-all'>
@@ -203,9 +203,19 @@ export function OTA() {
203203
</div>
204204
</div>
205205

206+
<div className='flex flex-col space-y-4'>
207+
<label className='mb-2 block text-sm font-medium'>Controller Signal Strength</label>
208+
<span className='font-light'>
209+
{rssi}dB{' '}
210+
<span
211+
className={`indicator-item status ml-2 ${rssi < -90 ? 'status-error' : rssi < -80 ? 'status-warning' : 'status-success'}`}
212+
></span>
213+
</span>
214+
</div>
215+
206216
{formData.spiffsTotal !== undefined && (
207217
<div className='flex flex-col space-y-2'>
208-
<label className='text-sm font-medium'>Storage (SPIFFS)</label>
218+
<label className='mb-2 block text-sm font-medium'>Storage (SPIFFS)</label>
209219
<div className='flex flex-col gap-1'>
210220
<div className='bg-base-300 h-3 w-full overflow-hidden rounded'>
211221
<div
@@ -298,25 +308,26 @@ export function OTA() {
298308
)}
299309
</button>
300310
</div>
301-
311+
302312
{rebuilding && (
303313
<div className='mt-3'>
304-
<div className='text-sm text-base-content/70 mb-1'>
305-
{rebuildProgress.status === 'starting' || rebuildProgress.status === 'scanning' || rebuildProgress.total === 0 ? (
306-
'Scanning shot history files...'
307-
) : (
308-
`Processing shot history files (${rebuildProgress.current}/${rebuildProgress.total})`
309-
)}
314+
<div className='text-base-content/70 mb-1 text-sm'>
315+
{rebuildProgress.status === 'starting' ||
316+
rebuildProgress.status === 'scanning' ||
317+
rebuildProgress.total === 0
318+
? 'Scanning shot history files...'
319+
: `Processing shot history files (${rebuildProgress.current}/${rebuildProgress.total})`}
310320
</div>
311321
<div className='bg-base-300 h-2 w-full overflow-hidden rounded'>
312322
<div
313323
className={`h-full transition-all duration-300 ${
314324
rebuildProgress.total === 0 ? 'bg-primary animate-pulse' : 'bg-primary'
315325
}`}
316-
style={{
317-
width: rebuildProgress.total > 0
318-
? `${(rebuildProgress.current / rebuildProgress.total) * 100}%`
319-
: '30%'
326+
style={{
327+
width:
328+
rebuildProgress.total > 0
329+
? `${(rebuildProgress.current / rebuildProgress.total) * 100}%`
330+
: '30%',
320331
}}
321332
/>
322333
</div>

0 commit comments

Comments
 (0)