Keskustele projektistasi
MicrocosmWorksInnovoimassa ja Arkkitehtuuria Digitaalisessa Kosmoksessa
TietoaYhteystiedot
MicrocosmWorksInnovoimassa ja suunnittelemassa digitaalista kosmosta

Toimitamme IT-ratkaisuja, joilla on merkitystä. Olemme intohimoisia teknologiasta, turvallisuudesta ja autamme yrityksiä kasvamaan luotettavan, innovatiivisen IT-infrastruktuurin kautta.

[email protected]
+91 7011868196
New Delhi, India

Ratkaisut

RakennaAI-tuotekehitysSaaS-tuotekehitysRäätälöity Ohjelmistokehitys
ModernisoiOhjelmiston ModernisointiAI-modernisointiPilvisovellusten Modernisointi
SkaalaaBackend ja Hajautetut JärjestelmätPilven SuorituskykytekniikkaLuotettavuus- ja SuorituskykytekniikkaAI-infrastruktuuri
LaajennaTuotekehitystiimit
Kaikki ratkaisutAI-agenttikehitysAI-videoplatformiHyvinvointi- ja kuntoilusovellukset

Palvelut

Digitaalinen konsultointiPilvi-infrastruktuuriSaaS-kehitysAI-kehitysVideoteknologia
ERP-kehitysZoho-mukautusOdoo-kehitysSalesforce-integraatioMukautettu CRM-kehitys
QuickBooks-integraatioIoT-ratkaisutLohkoketjukehitys
KyberturvallisuuskonsultointiIT-tuki - L3

AI Kasvuhubi

AI HubStartup-innovaatiotYrityskiihdyttämö

Resurssit

OivalluksetToimialan oppaatKäyttötapausmallitArkkitehtuurimallitTapaustutkimukset

Yritys

Tietoa meistäYhteystiedotKeskustele projektistasiTyömme

© 2026 MicrocosmWorks. Kaikki oikeudet pidätetään.

TietosuojakäytäntöKäyttöehdot
Takaisin oivalluksiin
IoT Development

Yhdistetyn annostelijasovelluksen rakentaminen

Mobiilisovelluksen rakentaminen, joka muodostaa parin ja ohjaa yhdistettyä annostelijalaitetta BLE:n kautta.

Mayank Joshi.webpMayank Chandra Joshi
•
September 7, 2026
•
Päivitetty September 24, 2026
•
6 min read
ChatGPT Image Sep 7, 2026, 12_49_11 PM (1).webp
6 min read

Useimmat kumppanisovellukset ovat ohuita BLE-kaukosäätimiä: napauta painiketta, kirjoita arvo, valmista. Annostelija ei voi olla niin ohut – annostelu on terveys tapahtuma, joka on kirjattava täsmälleen kerran, laite puhuu mukautettua binääriprotokollaa standardin GATT-profiilin sijaan, eikä "älä missaa annosta" voi riippua puhelimen hereillä olosta. Näin rakensimme polun napautuksesta kestävään, sovitettavissa olevaan tilaan, osana wellness & fitness app development -työtämme.

Yleiskatsaus

Toimialue Yhdistetty hyvinvointi — älykäs lisäravinteiden annostelu

Ydinteknologiat React Native + Expo, react-native-ble-plx, Zustand, NestJS, MongoDB 8 (transaktiot)

Avainominaisuudet Mukautettu BLE-komento-/telemetriaprotokolla, SMP/CBOR-laiteohjelmistopäivitykset, transaktiopohjainen annostelun kirjaaminen, aikavyöhyketietoiset muistutukset

Tila Kehityksen vaihe 2 alkaa

Haaste

Asiakkaamme kehitti yhdistetyn hyvinvointituotteen: laitteen, joka annostelee lisäravinteita ja jota ohjataan puhelimella. Tavanomainen tapa rakentaa kumppanisovellus – ja tapa, jolla useimmat on rakennettu – on ohut kaukosäädin, joka kirjoittaa ominaisuuden ja luottaa tulokseen. Se toimii hehkulampussa, mutta tuskin ollenkaan annostelijassa.

Tiesimme sen alusta alkaen, siksi emme rakentaneet sitä sillä tavalla. Ohuen etäohjausmallin rajoitukset ovat rakenteellisia, eivät hienosäätöongelmia:

  • Annostelu on kirjattava täsmälleen kerran. Se vähentää fyysistä varastoa, lasketaan päivittäiseen annokseen ja syöttää tietoja ravintoaineanalyyseihin. Kaksinkertainen laskenta tai menetetty kirjoitus vioittaa kaikki kolme.
  • Laite puhuu mukautettua protokollaa, ei profiilia. Komennot ovat kehyksellisiä binääripaketteja; ei ole valmiina ominaisuutta, joka tarkoittaisi "annostele yksi tabletti".
  • Komennoilla ja telemetrialla ei ole samaa muotoa. Sovellus kirjoittaa tiiviitä binäärikomentoja, mutta lukee takaisin JSON-telemetriaa (akku, lataus, patruunan tunnus, veden määrä) – eri ominaisuuksien kautta.
  • Laiteohjelmistopäivitykset käyttävät samaa yhteyttä. Laite on päivitettävissä kentällä, erillisen hallintapalvelun kautta, ilman toista työkalua.
  • Muistutukset eivät voi sijaita laitteessa. "Et ole annostellut tänään" on kysymys aikavyöhykkeistä, historiasta ja kaksoiskappaleiden poistamisesta – palvelimen huoli, ei puhelimen ajastin.

Perussyy oli yksinkertainen: annostelu ei ole painikkeen painallus, se on transaktio – sekä tiedonsiirrossa että tietokannassa. Malli, joka käsittelee sitä "lähetä ja unohda" -kirjoituksena, ei voi tehdä kummastakaan puolesta luotettavaa.

Ratkaisumme

Jaoimme vastuualueet niin, että jokainen kerros tekee sen, missä se on paras: puhelin orkestroi, laite suorittaa mukautetun protokollan, joka on määritetty IoT application development -käytäntömme kautta, ja pilvi on transaktiojärjestelmä – muistutukset hoidetaan kokonaan palvelinpuolella.

Arkkitehtuuri

  • React Native + Expo + Zustand — BluetoothStore omistaa BLE-yhteyden, annosteluvirran ja telemetrian, joka säilytetään AsyncStorage-varastoon.
  • react-native-ble-plx — skannaus, yhteys/uudelleenyhteys ja ominaisuuksien luku/kirjoitus.
  • Mukautettu komentokerros — rakentaa kehyksellisiä binäärikomentoja laitteelle ja käyttää CBOR:ia SMP-palvelun kautta laiteohjelmistopäivityksiin.
  • NestJS API — annostelu- ja aikataulutusrajapinnat, jotka on rakennettu samalle SaaS application development -perustalle, jota käytämme kaikissa asiakastuotteissa; kirjaa jokaisen annostelun MongoDB-transaktion sisällä.
  • MongoDB 8 (Mongoose) — tietojärjestelmä, sekä kirjoitushetkellä luodut yhteenvetokokoelmat, joita alavirran analytiikka lukee.
  • NestJS Schedule cron-työt + Expo push (jonotettu ActiveMQ/STOMP:n kautta) — aikavyöhyketietoiset muistutukset, kaksoiskappaleet poistettu Mongo-lokien kautta.
  • Sentry (mobiili) — tuotantoympäristön virheiden seuranta sovelluksessa.


architecture-ble-dispenser.webp

Mukautettu tiedonsiirtoprotokolla

Mikä tahansa BLE-tuotteen haastava osa on se, että laite ei puhu standardikieltä. Meidän laitteemme tarjoaa komento-/telemetriapalvelun ja erillisen laiteohjelmisto (SMP) -palvelun. Sovellus muodostaa yhteyden react-native-ble-plx:n avulla ja tilaa sitten telemetrian – joka saapuu JSON-muodossa ilmoitusominaisuuden kautta:

// BluetoothStore.ts — react-native-ble-plx + Zustand

const device = await bleManager.connectToDevice(deviceId, { autoConnect: true });

await device.discoverAllServicesAndCharacteristics();

// Telemetry: JSON over the notify characteristic (UUIDs are app-side constants).

bleManager.monitorCharacteristicForDevice(device.id, CH_SERVICE_UUID, TX_UUID, (_err, c) => {

  if (!c?.value) return;

  const t = JSON.parse(base64ToString(c.value));

  // { battery_percentage, charging_status, cartridge_id, water_qty, sequence, timestamp }

  set({ batteryPercentage: Number(t.battery_percentage), chargingStatus: t.charging_status });

});

 

Annostelu on tiivis, kehyksellinen binäärikomento – aloitustunniste, komennon tunnus, pituus, patruunabitti, luku-/kirjoitustunniste ja lopetustunniste – base64-koodattu ja kirjoitettu komento-ominaisuuteen. (Kirjaimelliset UUID:t ja kehystunnisteet on piilotettu tässä.)

// Frame shape: [SOF] [CMD] [LEN] [DATA] [RW] [EOF]  — built by the command service.

const command = SNBCommandService.buildDispenseNutritionCommand(cartridgeId); // CMD = DISPENSE

await bleManager.writeCharacteristicWithResponseForDevice(

  device.id, CH_SERVICE_UUID, RX_UUID,

  SNBCommandService.uint8ArrayToBase64(command),
 
);

 

Sovellus odottaa laitteen kuittausta (se täsmää komennon tunnuksen takaisin vastauskehyksestä) ennen kuin se käsittelee annostelua todellisena – ja vasta silloin kirjaa sen palvelinpuolelle. Laiteohjelmistopäivitykset käyttävät samaa yhteyttä, mutta eri kieltä: CBOR-palautteita (chunked CBOR payloads) SMP-palvelun kautta.

Napautuksesta kirjaamiseen

Vahvistettu annostelu muuttuu pysyväksi tilaksi yhden päätepisteen kautta — POST /dispense/tablet/:cartridgeId — joka kirjoittaa yhden MongoDB-transaktion sisällä, jotta kaikki puoli tusinaa vaikutusta joko tapahtuvat tai eivät ollenkaan:


// dispense.service.ts — record exactly once, atomically

await session.withTransaction(async () => {

  await this.dispensed.create([{ cartridgeId, cartridgeModalId, dispensedBy: userId, dispensedAt }], { session });

  // write-time roll-up: totalDaysConsumed only increments on the first dose of the day

  await this.monthly.findOneAndUpdate(

    { userId, cartridgeModalId, month, year },

    { $inc: { totalTablets: 1, ...(firstDoseToday ? { totalDaysConsumed: 1 } : {}) } },

    { upsert: true, session },

  );

  await this.cartridge.updateOne({ cartridgeId }, { $inc: { tablets: -1 } }, { session });

  await this.dailyDose.updateOne({ userId, dateLocal }, { $inc: { tabletsTaken: 1 } }, { upsert: true, session });

  await this.notifications.cancelPending(userId, 'SUPPLEMENT_REMINDER', { session }); // mark IS_MISSED

});

 

Tuo yksi transaktio päivittää annostelulokin, kuukausittaisen yhteenvetotiedon, fyysisen varaston, päivittäisen annosmäärän ja kaikki odottavat muistutukset – juuri siksi annostelun on oltava transaktio, ei pelkkä kirjoitus.

Muistutukset ovat palvelimen asia

Kun annostelu on tallennettu pysyvästi, kysymykset, joihin puhelimen ajastin ei voinut vastata, muuttuvat rutiiniksi – ja niihin vastaavat cron-työt, eivät sovellus:

  • Onko tämä käyttäjä annostellut tänään, omalla aikavyöhykkeellään?
  • Onko patruuna tyhjä (vaihda) vai varasto tyhjä (tilaa lisää), vai molemmat (lopettaminen)?
  • Ovatko he etääntyneet terveysalueesta, jota he aiemmin käyttivät?

Kolme @nestjs/schedule -palvelua hoitaa nämä – aikataulu-/annosmuistutus, patruunan tilan muistutus ja terveysalueen ylittävä toimettomuusmuistutus. Jokainen ratkaisee käyttäjän paikallisen ajan date-fns-tz:n avulla, tarkistaa Mongosta, ovatko he annostelleet tänään, poistaa kaksoiskappaleet lokikokoelmaa vastaan ja jonottaa Expo push -ilmoituksen ActiveMQ:n kautta. Laite ei ole koskaan mukana.

Tulokset

Suunnittelu siten, että "annostelu on transaktio" ohuen etäohjauskirjoituksen sijaan, muutti sitä, mitä järjestelmä voi taata:

  • Täsmälleen kerran -kirjaaminen. Annostelu päivittää lokin, yhteenvetoja, varaston ja päivittäisen annoksen atomisesti – ei kaksinkertaisia laskentoja, ei osittaisia kirjoituksia.
  • Dokumentoitu laiteprotokolla, mukaan lukien kenttäpäivitykset. Komennot ja telemetria ovat ensiluokkaisia, ja laiteohjelmistopäivitykset lähetetään saman yhteyden kautta SMP/CBOR:n avulla.
  • Muistutukset, jotka ovat oikein, eivät likimääräisiä. Aikavyöhyke- ja historia-tietoiset, ja palvelinpuolella kaksoiskappaleet poistetut – joten ne laukeavat riippumatta siitä, onko sovellus auki.
  • Analytiikka, johon voi luottaa. Koska jokainen annostelu kootaan kirjoitushetkellä, kaavioita ja noudattamista syöttävä data on aina johdonmukaista lokin kanssa.

API, cron-työt ja push-jono pyörivät cloud infrastructure services -palveluidemme kautta hallitussa infrastruktuurissa, joten samat luotettavuustakuut pysyvät voimassa laitekannan ja käyttäjäkunnan kasvaessa.

Technology Stack: React Native · Expo · TypeScript · react-native-ble-plx · Zustand · CBOR (SMP firmware) · NestJS · MongoDB 8 · Mongoose (transactions) · @nestjs/schedule · ActiveMQ / STOMP · Expo Server SDK · JWT · AWS S3 · AWS SES · Sentry (mobile)


Lue lisää tiimiltämme

1. Apple Healthin ja Health Connectin synkronointi

2. Personoitu reseptihaku: nouto, joka tietää mitä sinun tulisi syödä seuraavaksi

3. Kanavan logon optimointi eri videoresoluutioille

 

IoTBLEMobile AppConnectivity
Mayank Joshi.webp

Tietoa kirjoittajasta

Mayank Chandra Joshi

AI & Cloud Solutions Expert at MicrocosmWorks

Building innovative AI-powered solutions and helping businesses transform through cutting-edge technology.

Haluatko oppia lisää?

Ota meihin yhteyttä keskustellaksemme siitä, kuinka voimme auttaa toteuttamaan nämä ratkaisut liiketoiminnassasi.

Ota yhteyttä

Usein kysytyt kysymykset

The app uses react-native-ble-plx to connect to the dispenser and communicate through its BLE characteristics. Dispense commands are built as framed binary packets containing fields such as the command ID, cartridge information, length, and read/write flag, while device telemetry is received separately as JSON.

A dispense is recorded only after the device acknowledges the corresponding command. The backend then records the confirmed dispense inside a MongoDB transaction, atomically updating the dispense log, stock, daily dose count, monthly roll-up, and pending reminder so the related state changes cannot be partially committed.

The dispenser uses a separate firmware management service based on the Simple Management Protocol (SMP). Firmware update data is transferred as chunked CBOR payloads over the same BLE connection, allowing the device to receive field updates without requiring a separate application or connection mechanism.

Dose reminders are handled server-side rather than by relying on a phone timer. NestJS scheduled services determine the user's local time, check MongoDB for the user's dosing history, de-duplicate reminder events, and queue Expo push notifications through ActiveMQ/STOMP. This allows reminders to be generated even when the mobile app is not open.

The system uses React Native, Expo, TypeScript, react-native-ble-plx, Zustand, NestJS, MongoDB 8 with Mongoose transactions, CBOR over SMP for firmware updates, @nestjs/schedule, ActiveMQ/STOMP, Expo Server SDK, JWT, AWS S3, AWS SES, and Sentry. Together, these components support BLE communication, transactional dispense recording, firmware management, reminders, storage, and mobile error tracking.

Comments (0)

Share your thoughts and join the conversation

Leave a Comment

Your email will not be published

No comments yet

Be the first to share your thoughts!