From eefde5a1b16d35bb16ad3986c630feff9333e87a Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Sun, 9 Aug 2026 19:47:28 -0500 Subject: [PATCH 1/7] fix(fase-10): fix pressure calculation in board and app --- apps/mobile/src/screens/devices.tsx | 2 +- firmware/src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mobile/src/screens/devices.tsx b/apps/mobile/src/screens/devices.tsx index 21dcab7..0f1d4e6 100644 --- a/apps/mobile/src/screens/devices.tsx +++ b/apps/mobile/src/screens/devices.tsx @@ -178,7 +178,7 @@ export function DevicesScreen() { setSensorData((prev) => ({ ...prev, - pressure_hpa: pressValue / 100, + pressure_hpa: pressValue, })); }, ); diff --git a/firmware/src/main.c b/firmware/src/main.c index ec70069..7585f03 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -171,7 +171,7 @@ int main(void) full_reading.temperature_c = temp.val1 * 100 + temp.val2 / 10000; full_reading.humidity_pct = hum.val1 * 100 + hum.val2 / 10000; - full_reading.pressure_hpa = press.val1 * 100 + press.val2 / 10000; + full_reading.pressure_hpa = press.val1 * 10 + press.val2 / 100000; full_reading.pm1_0_ugm3 = pmsa003i_data_raw.pm1_0; full_reading.pm2_5_ugm3 = pmsa003i_data_raw.pm2_5; full_reading.pm10_ugm3 = pmsa003i_data_raw.pm10_0; From bcc8f234fb55c0622a5802fb7f00500a126c5688 Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Sun, 9 Aug 2026 22:17:41 -0500 Subject: [PATCH 2/7] feat(fase-10): add device settings columns to device table, and create endpoint to update device settings and thresholds --- .../backend/src/devices/devices.controller.ts | 14 +++++++++++ apps/backend/src/devices/devices.service.ts | 25 +++++++++++++++++++ .../devices/dto/create-device-settings.dto.ts | 5 ++++ .../devices/dto/update-device-settings.dto.ts | 6 +++++ .../src/devices/entities/device.entity.ts | 6 +++++ 5 files changed, 56 insertions(+) create mode 100644 apps/backend/src/devices/dto/create-device-settings.dto.ts create mode 100644 apps/backend/src/devices/dto/update-device-settings.dto.ts diff --git a/apps/backend/src/devices/devices.controller.ts b/apps/backend/src/devices/devices.controller.ts index 888dafc..d1a6572 100644 --- a/apps/backend/src/devices/devices.controller.ts +++ b/apps/backend/src/devices/devices.controller.ts @@ -16,6 +16,7 @@ import { } from './dto/update-device.dto'; import { User } from 'src/decorators/user.decorator'; import { Public } from 'src/decorators/public'; +import { UpdateDeviceSettingsDto } from './dto/update-device-settings.dto'; @Controller('devices') export class DevicesController { constructor(private readonly devicesService: DevicesService) {} @@ -44,6 +45,19 @@ export class DevicesController { return this.devicesService.updateStatus(deviceToken, updateDeviceStatusDto); } + @Patch(':id/settings') + updateSettings( + @Param('id') id: string, + @User() user: any, + @Body() updateDeviceSettingsDto: UpdateDeviceSettingsDto, + ) { + return this.devicesService.updateSettings( + id, + user, + updateDeviceSettingsDto, + ); + } + @Patch(':id') update( @Param('id') id: string, diff --git a/apps/backend/src/devices/devices.service.ts b/apps/backend/src/devices/devices.service.ts index 099dc49..480f4e4 100644 --- a/apps/backend/src/devices/devices.service.ts +++ b/apps/backend/src/devices/devices.service.ts @@ -8,6 +8,7 @@ import { Device } from './entities/device.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import * as crypto from 'crypto'; +import { UpdateDeviceSettingsDto } from './dto/update-device-settings.dto'; @Injectable() export class DevicesService { @@ -74,6 +75,30 @@ export class DevicesService { return updatedDevice; } + async updateSettings( + id: string, + user: any, + updateDeviceSettingsDto: UpdateDeviceSettingsDto, + ): Promise { + const device = await this.devicesRepository.findOneBy({ + user: { id: user.id }, + deviceId: id, + }); + + if (!device) { + throw new HttpException('Device does not exist', HttpStatus.NOT_FOUND); + } + + const updatedDeviceSettings = { + ...device, + ...updateDeviceSettingsDto, + }; + + await this.devicesRepository.save(updatedDeviceSettings); + + return updatedDeviceSettings; + } + async updateStatus( deviceToken: string, updateDeviceStatusDto: UpdateDeviceStatusDto, diff --git a/apps/backend/src/devices/dto/create-device-settings.dto.ts b/apps/backend/src/devices/dto/create-device-settings.dto.ts new file mode 100644 index 0000000..67f2485 --- /dev/null +++ b/apps/backend/src/devices/dto/create-device-settings.dto.ts @@ -0,0 +1,5 @@ +export class CreateDeviceSettingsDto { + samplingIntervalSec: number; + temperatureThreshold: number; + pm25Threshold: number; +} diff --git a/apps/backend/src/devices/dto/update-device-settings.dto.ts b/apps/backend/src/devices/dto/update-device-settings.dto.ts new file mode 100644 index 0000000..fd2c102 --- /dev/null +++ b/apps/backend/src/devices/dto/update-device-settings.dto.ts @@ -0,0 +1,6 @@ +import { CreateDeviceSettingsDto } from './create-device-settings.dto'; +import { PartialType } from '@nestjs/mapped-types'; + +export class UpdateDeviceSettingsDto extends PartialType( + CreateDeviceSettingsDto, +) {} diff --git a/apps/backend/src/devices/entities/device.entity.ts b/apps/backend/src/devices/entities/device.entity.ts index 610c45d..1be3b50 100644 --- a/apps/backend/src/devices/entities/device.entity.ts +++ b/apps/backend/src/devices/entities/device.entity.ts @@ -27,4 +27,10 @@ export class Device { user: User; @Column({ unique: true }) deviceToken: string; + @Column({ type: 'int', default: 300 }) + samplingIntervalSec: number; + @Column({ nullable: true, type: 'decimal' }) + temperatureThreshold: number; + @Column({ nullable: true, type: 'decimal' }) + pm25Threshold: number; } From df264bf27fa12841e06f88c0b6785f3cbf487c49 Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Sun, 16 Aug 2026 21:39:11 -0500 Subject: [PATCH 3/7] feat(fase-10): add write characteristic and callback to receive reading interval settings from ble --- firmware/src/main.c | 22 +++++++++++-- firmware/src/sensor_service.c | 59 ++++++++++++++++++++++++++++++++++- firmware/src/sensor_service.h | 19 ++++++----- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/firmware/src/main.c b/firmware/src/main.c index 838754f..c70f799 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -12,7 +12,6 @@ #define RETRY_DELAY_MS 10000 #define WARM_UP_INTERVAL_MS 10000 -#define WAKE_UP_INTERVAL 10000 #define LED0_NODE DT_ALIAS(led0) #define I2C_NODE DT_NODELABEL(bme680) @@ -27,6 +26,8 @@ static const struct device *const dev_i2c = DEVICE_DT_GET(I2C_NODE); static const pmsa003i_config_t pmsa003i_config = { .i2c = I2C_DT_SPEC_GET(I2C_PMSA003I_NODE)}; +static uint32_t wake_up_interval = 300000; // Default wake-up interval in milliseconds + static struct sensor_value temp; static struct sensor_value hum; static struct sensor_value press; @@ -65,6 +66,12 @@ struct bt_conn_cb connection_callbacks = { }; +static void on_reading_interval_changed(const uint32_t reading_interval_ms) +{ + wake_up_interval = reading_interval_ms; + LOG_INF("Wake-up interval updated to %u ms", wake_up_interval); +} + int main(void) { int ret; @@ -91,6 +98,17 @@ int main(void) return -1; } + struct sensor_settings_cb settings_callback = { + .reading_interval_cb = on_reading_interval_changed, + }; + + ret = settings_callback_init(&settings_callback); + if (ret) + { + LOG_ERR("Failed to read settings callback (err %d)", ret); + return -1; + } + LOG_INF("Advertising started %d\n", ret); if (!device_is_ready(dev_i2c)) @@ -225,6 +243,6 @@ int main(void) gpio_pin_toggle_dt(&led); // bt_le_adv_stop(); - k_sleep(K_MSEC(WAKE_UP_INTERVAL)); + k_sleep(K_MSEC(wake_up_interval)); } } diff --git a/firmware/src/sensor_service.c b/firmware/src/sensor_service.c index 677baf8..95585b4 100644 --- a/firmware/src/sensor_service.c +++ b/firmware/src/sensor_service.c @@ -6,7 +6,11 @@ LOG_MODULE_REGISTER(sensor_service, LOG_LEVEL_DBG); +#define MIN_SAMPLING_INTERVAL_MS (1U * 60U * 1000U) +#define MAX_SAMPLING_INTERVAL_MS (30U * 60U * 1000U) + static bool notify_sensor_enabled; +static struct sensor_settings_cb settings_cb; static void airnode_ccc_sensor_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) @@ -14,6 +18,45 @@ static void airnode_ccc_sensor_cfg_changed(const struct bt_gatt_attr *attr, notify_sensor_enabled = (value == BT_GATT_CCC_NOTIFY); } +static ssize_t write_ble_reading_interval(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, + uint16_t len, uint16_t offset, uint8_t flags) +{ + LOG_DBG("Attribute write, handle: %u, conn: %p", attr->handle, (void *)conn); + + if (len != sizeof(uint32_t)) + { + LOG_DBG("Sampling Interval: Incorrect data length"); + return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); + } + + if (offset != 0) + { + LOG_DBG("Sampling Interval: Incorrect data offset"); + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + if (settings_cb.reading_interval_cb) + { + // Read the received value + uint32_t interval_ms = *((uint32_t *)buf); + + if (interval_ms < MIN_SAMPLING_INTERVAL_MS || interval_ms > MAX_SAMPLING_INTERVAL_MS) + { + LOG_DBG("Sampling Interval: Value out of bounds"); + return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); + } + + // Call the application callback function to update the reading interval + settings_cb.reading_interval_cb(interval_ms); + } + else + { + LOG_DBG("Sampling Interval: Incorrect value"); + return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); + } + return len; +} + BT_GATT_SERVICE_DEFINE(airnode_service, BT_GATT_PRIMARY_SERVICE(BT_UUID_ESS), @@ -45,7 +88,21 @@ BT_GATT_SERVICE_DEFINE(airnode_service, BT_GATT_CHARACTERISTIC(BT_UUID_GATT_PM10CONC, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, NULL, NULL, NULL), BT_GATT_CCC(airnode_ccc_sensor_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), ); + BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + + BT_GATT_CHARACTERISTIC(BT_UUID_SENSOR_SETTINGS, BT_GATT_CHRC_WRITE, BT_GATT_PERM_WRITE, NULL, write_ble_reading_interval, NULL), + +); + +int settings_callback_init(struct sensor_settings_cb *callbacks) +{ + if (callbacks) + { + settings_cb.reading_interval_cb = callbacks->reading_interval_cb; + } + + return 0; +} int send_sensor_notify(struct airnode_readings sensor_value, SensorDataType type) { diff --git a/firmware/src/sensor_service.h b/firmware/src/sensor_service.h index 3db66b7..167063a 100644 --- a/firmware/src/sensor_service.h +++ b/firmware/src/sensor_service.h @@ -23,19 +23,22 @@ typedef enum PM10 } SensorDataType; -/** Initial Service UUID - 4cff14aa-fca7-4da8-89d7-952ac08b3085 */ -#define BT_UUID_SENSOR_SERVICE_VAL \ - BT_UUID_128_ENCODE(0x4cff14aa, 0xfca7, 0x4da8, 0x89d7, 0x952ac08b3085) +typedef void (*reading_interval_cb_t)(const uint32_t reading_interval_ms); -/** Value Characteristic UUID - 8123e770-73b5-4b07-aa24-99f776d1e37a */ -#define BT_UUID_SENSOR_DATA_VAL \ - BT_UUID_128_ENCODE(0x8123e770, 0x73b5, 0x4b07, 0xaa24, 0x99f776d1e37a) +struct sensor_settings_cb +{ + reading_interval_cb_t reading_interval_cb; +}; + +/** Value Characteristic UUID - d87f823c-4c33-4ddd-9ac4-4ada6ad5e913 */ +#define BT_UUID_SENSOR_SETTINGS_VAL \ + BT_UUID_128_ENCODE(0xd87f823c, 0x4c33, 0x4ddd, 0x9ac4, 0x4ada6ad5e913) /** Convert the array to a generic UUID */ -#define BT_UUID_SENSOR BT_UUID_DECLARE_128(BT_UUID_SENSOR_SERVICE_VAL) -#define BT_UUID_SENSOR_DATA BT_UUID_DECLARE_128(BT_UUID_SENSOR_DATA_VAL) +#define BT_UUID_SENSOR_SETTINGS BT_UUID_DECLARE_128(BT_UUID_SENSOR_SETTINGS_VAL) int send_sensor_notify(struct airnode_readings sensor_value, SensorDataType type); +int settings_callback_init(struct sensor_settings_cb *callbacks); #endif // SENSOR_SERVICE_H \ No newline at end of file From 2437383f6f946ee8ae1c1fa06ca1e6dc0cc21590 Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Tue, 18 Aug 2026 22:55:52 -0500 Subject: [PATCH 4/7] feat(fase-10): add patch device settings api call to update sampling interval in db --- apps/mobile/src/api/deviceService.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 apps/mobile/src/api/deviceService.ts diff --git a/apps/mobile/src/api/deviceService.ts b/apps/mobile/src/api/deviceService.ts new file mode 100644 index 0000000..4408788 --- /dev/null +++ b/apps/mobile/src/api/deviceService.ts @@ -0,0 +1,17 @@ +import { instance } from "./axios"; + +export const patchDeviceSettings = async ( + deviceId: string, + samplingInterval: number, +) => { + const samplingIntervalSec = samplingInterval * 60; + + try { + const response = await instance.patch(`devices/${deviceId}/settings`, { + samplingIntervalSec: samplingIntervalSec, + }); + return response.data; + } catch (error) { + console.log(error); + } +}; From 2a127b8791cbd754317b724cb264731547ce4f8b Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Tue, 18 Aug 2026 22:57:09 -0500 Subject: [PATCH 5/7] feat(fase-10): update settings screen with ble write to update sampling interval --- apps/mobile/src/api/axios.ts | 2 +- apps/mobile/src/screens/dashboard.tsx | 46 ++++++++++++--- apps/mobile/src/screens/settings.tsx | 81 ++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 11 deletions(-) diff --git a/apps/mobile/src/api/axios.ts b/apps/mobile/src/api/axios.ts index 2ab7f4c..f11ffb7 100644 --- a/apps/mobile/src/api/axios.ts +++ b/apps/mobile/src/api/axios.ts @@ -2,7 +2,7 @@ import axios from "axios"; import { authStore } from "../stores/authStore"; export const instance = axios.create({ - baseURL: "http://192.168.1.74:3000/", + baseURL: "http://192.168.5.105:3000/", timeout: 10000, }); diff --git a/apps/mobile/src/screens/dashboard.tsx b/apps/mobile/src/screens/dashboard.tsx index 5330036..b1cadb9 100644 --- a/apps/mobile/src/screens/dashboard.tsx +++ b/apps/mobile/src/screens/dashboard.tsx @@ -32,7 +32,9 @@ const RangeItem = ({ name, onPress, isSelected }: RangeProps) => ( ]} > - {name} + + {name} + ); @@ -209,7 +211,7 @@ export function DashboardScreen() { - Dashboard Screen + Air Quality Dashboard {rangeList.map((r) => ( ))} - - Download CSV + + Download CSV {sensorList.map((s) => ( @@ -241,9 +240,18 @@ export function DashboardScreen() { ); } +const ACCENT_COLOR = "#0f766e"; + const styles = StyleSheet.create({ + title: { + fontSize: 32, + fontWeight: "600", + marginTop: 140, + color: "#1f2937", + }, + item: { - backgroundColor: "#00ffc8fd", + backgroundColor: "#e5e7eb", padding: 12, borderRadius: 20, alignSelf: "center", @@ -251,10 +259,30 @@ const styles = StyleSheet.create({ }, activeItem: { - backgroundColor: "red", + backgroundColor: ACCENT_COLOR, padding: 12, borderRadius: 20, alignSelf: "center", paddingHorizontal: 20, }, + + itemText: { + color: "#374151", + }, + + activeItemText: { + color: "white", + fontWeight: "600", + }, + + csvButton: { + backgroundColor: ACCENT_COLOR, + padding: 10, + borderRadius: 20, + }, + + csvButtonText: { + color: "white", + fontWeight: "bold", + }, }); diff --git a/apps/mobile/src/screens/settings.tsx b/apps/mobile/src/screens/settings.tsx index d7e99e0..8fefc57 100644 --- a/apps/mobile/src/screens/settings.tsx +++ b/apps/mobile/src/screens/settings.tsx @@ -1,5 +1,10 @@ -import { View, Text, Button } from "react-native"; +import { View, Text, Button, TextInput, Alert, StyleSheet } from "react-native"; import { authStore } from "../stores/authStore"; +import { useState } from "react"; +import { patchDeviceSettings } from "../api/deviceService"; +import { manager } from "../ble/bleManager"; +import { deviceStore } from "../stores/deviceStore"; +import { Buffer } from "buffer"; import * as SecureStore from "expo-secure-store"; @@ -10,6 +15,51 @@ export function SettingsScreen() { SecureStore.deleteItemAsync("refreshToken"); }; + const onUpdateSamplingInterval = async () => { + const intervalInMin = parseInt(samplingInterval, 10); + + const intervalInSec = intervalInMin * 60; + + const intervalInMs = intervalInSec * 1000; + + const deviceId = deviceStore.getState().deviceId; + + if (intervalInMin < 1 || intervalInMin > 30) return; + + const buf = Buffer.alloc(4); + + buf.writeUint32LE(intervalInMs, 0); + + const base64Data = buf.toString("base64"); + + patchDeviceSettings(deviceId, intervalInSec); + + const services = await manager.servicesForDevice(deviceId); + const essService = services.find((s) => s.uuid.includes("181a")); + if (!essService) return; + + const characteristics = await manager.characteristicsForDevice( + deviceId, + essService.uuid, + ); + + manager.writeCharacteristicWithResponseForDevice( + deviceId, + essService.uuid, + characteristics[6].uuid, + base64Data, + ); + }; + + const [samplingInterval, setSamplingInterval] = useState(""); + + const handleChangeText = (inputText: string) => { + const cleanNumber = inputText.replace(/[^0-9]/g, ""); + + setSamplingInterval(cleanNumber); + }; + console.log(samplingInterval); + return ( Settings Screen + + + Set sampling interval + + + + + + ); } + +const styles = StyleSheet.create({ + input: { + height: 40, + margin: 12, + borderWidth: 1, + padding: 10, + }, +}); From fa1a8b897ed10a97cef21ff5ead5081ce5b9225c Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Wed, 19 Aug 2026 06:15:49 -0500 Subject: [PATCH 6/7] fix(fase-10): add error handling to settings, readings, and login --- apps/mobile/src/screens/dashboard.tsx | 1 + apps/mobile/src/screens/login.tsx | 26 +++++++++++++++++++------- apps/mobile/src/screens/settings.tsx | 12 +++++++++++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/apps/mobile/src/screens/dashboard.tsx b/apps/mobile/src/screens/dashboard.tsx index b1cadb9..1419001 100644 --- a/apps/mobile/src/screens/dashboard.tsx +++ b/apps/mobile/src/screens/dashboard.tsx @@ -225,6 +225,7 @@ export function DashboardScreen() { Download CSV + {!readings && Data could not be loaded} {sensorList.map((s) => ( { - const response = await login(email, password); + try { + const response = await login(email, password); - if (response) { - const { accessToken, refreshToken } = response; + if (response) { + const { accessToken, refreshToken } = response; - authStore.getState().login(accessToken, refreshToken); - save("accessToken", accessToken); - save("refreshToken", refreshToken); + authStore.getState().login(accessToken, refreshToken); + save("accessToken", accessToken); + save("refreshToken", refreshToken); + } + } catch (error) { + if (error.response) { + if (error.response.status == 401) { + Alert.alert("Error", "Authentication error"); + } else { + Alert.alert("Error", "Something went wrong"); + } + } else { + Alert.alert("Error", "Network error"); + } } }; diff --git a/apps/mobile/src/screens/settings.tsx b/apps/mobile/src/screens/settings.tsx index 8fefc57..2bdc5d3 100644 --- a/apps/mobile/src/screens/settings.tsx +++ b/apps/mobile/src/screens/settings.tsx @@ -24,7 +24,17 @@ export function SettingsScreen() { const deviceId = deviceStore.getState().deviceId; - if (intervalInMin < 1 || intervalInMin > 30) return; + if ( + intervalInMin < 1 || + intervalInMin > 30 || + Number.isNaN(intervalInMin) + ) { + Alert.alert( + "Out of range", + "The number must be between 1 and 30 minutes", + ); + return; + } const buf = Buffer.alloc(4); From 6743fd05d3a59af584100c83cf6235bd1dec625e Mon Sep 17 00:00:00 2001 From: David Tobasura Date: Thu, 20 Aug 2026 20:49:19 -0500 Subject: [PATCH 7/7] fix(fase-10): error handling for ble disconnection on settings and logout, Add login throw error --- apps/mobile/src/api/authService.ts | 2 +- apps/mobile/src/screens/settings.tsx | 37 +++++++++++++++++----------- apps/mobile/src/stores/authStore.ts | 9 ++++--- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/apps/mobile/src/api/authService.ts b/apps/mobile/src/api/authService.ts index 3d337ff..cdb1a67 100644 --- a/apps/mobile/src/api/authService.ts +++ b/apps/mobile/src/api/authService.ts @@ -8,7 +8,7 @@ export const login = async (email: string, password: string) => { }); return response.data; } catch (error) { - console.log(error); + throw error; } }; diff --git a/apps/mobile/src/screens/settings.tsx b/apps/mobile/src/screens/settings.tsx index 2bdc5d3..e4cc6f0 100644 --- a/apps/mobile/src/screens/settings.tsx +++ b/apps/mobile/src/screens/settings.tsx @@ -44,21 +44,28 @@ export function SettingsScreen() { patchDeviceSettings(deviceId, intervalInSec); - const services = await manager.servicesForDevice(deviceId); - const essService = services.find((s) => s.uuid.includes("181a")); - if (!essService) return; - - const characteristics = await manager.characteristicsForDevice( - deviceId, - essService.uuid, - ); - - manager.writeCharacteristicWithResponseForDevice( - deviceId, - essService.uuid, - characteristics[6].uuid, - base64Data, - ); + try { + const services = await manager.servicesForDevice(deviceId); + const essService = services.find((s) => s.uuid.includes("181a")); + if (!essService) return; + + const characteristics = await manager.characteristicsForDevice( + deviceId, + essService.uuid, + ); + + manager.writeCharacteristicWithResponseForDevice( + deviceId, + essService.uuid, + characteristics[6].uuid, + base64Data, + ); + } catch (error) { + Alert.alert( + "Problem saving settings", + "Retry connecting to your device and try again", + ); + } }; const [samplingInterval, setSamplingInterval] = useState(""); diff --git a/apps/mobile/src/stores/authStore.ts b/apps/mobile/src/stores/authStore.ts index fe1e5a9..e876787 100644 --- a/apps/mobile/src/stores/authStore.ts +++ b/apps/mobile/src/stores/authStore.ts @@ -25,9 +25,12 @@ export const authStore = create((set) => ({ const deviceId = deviceStore.getState().deviceId; if (deviceId) { - await manager.cancelDeviceConnection(deviceId); - - console.log("Device disconnected"); + try { + await manager.cancelDeviceConnection(deviceId); + console.log("Device disconnected"); + } catch (error) { + console.error("Problem disconnecting device ", error); + } } set({