1 contributor
147 lines | 4.914kb

ChargedDevice Entity

Reprezentarea unui dispozitiv care se încarcă prin meter.

Responsabilități

  • Modelarea unui dispozitiv (iPhone, Watch, Charger, Powerbank, Other)
  • Gestionarea sesiunilor de încărcare
  • Colectarea de măsurători durante sesiune
  • Calculul integrității şi detectării conflictelor

Invarianţi

  • MUST: Fiecare ChargedDevice are un id (UUID) unic
  • MUST: O sesiune de încărcare are timestamp-uri valide: startTime <= currentTime <= endTime
  • MUST: Măsurătorile într-o sesiune sunt ordonate cronologic
  • MUST: O sesiune activă pe un dispozitiv trebuie să aibă un singur Meter asociat
  • MUST: Energia calculată (Wh) trebuie să fie ne-negativă
  • SHOULD: Un device cu 0 măsurători ar trebui marcat pentru curatare pe CloudKit
  • MAY: Duplicate sessions pe același MAC pot fi mergate după detectare

API Public

Proprietăţi

Proprietate Tip Descriere Observaţii
id UUID Identificator unic Generat la creare
deviceName String Nume ales de utilizator De ex: "My iPhone 15"
deviceClass ChargedDeviceClass Tip: iPhone, Watch, Charger, Powerbank, Other
kind ChargedDeviceKind Device sau Charger Derivat din deviceClass
createdAt Date Data creării Immutable
chargeRecords [ChargeRecord] Lista sesiunilor de încărcare Sorted by startTime
totalEnergy Double Total Wh consumat/furnizat Calculat din sesiuni
lastChargedAt Date? Data ultimei sesiuni Nullable

Metode

// Gestionare sesiuni
func startSession(meter: Meter) -> ChargeRecord
// MUST: sessionID este UUID unic
// MUST: startTime = now()
// MUST: retur ChargeRecord cu status "active"

func recordMeasurement(_ measurement: Measurement, in session: ChargeRecord)
// MUST: measurement.timestamp > session.startTime
// SHOULD: measure-urile sunt colectate la ~1Hz
// MUST: nu merge dacă sesiunea e finalizată

func endSession(_ record: ChargeRecord)
// MUST: endTime = now()
// MUST: calculează total energy din măsurători
// MUST: marchez sesiunea ca "completed"

func recalculateTotalEnergy()
// Recalculează sum-ul de Wh din toate sesiunile
// SHOULD: se apelează după conflict resolution

// Naming
func renameToDevice(_ newName: String)
// MUST: actualizează proprietatea şi persistă

// Conflict handling
func mergeWith(_ other: ChargedDevice, keepingRecords: Bool = true)
// MUST: combină sessions de pe ambele device-uri
// MUST: remove-ă duplicates după MAC address
// SHOULD: logs merge operation pentru debug

Comportamente critice

Sesiuni de încărcare

  • MUST: Doar o singură sesiune per device poate fi activă la orice moment
  • MUST: Sesiunile completate sunt imutable
  • SHOULD: Sesiunile care durează > 24h sunt marcate cu warning
  • MAY: Sesiuni orphaned (meter deconectat > 1h) pot fi finalizate automat

Calculul energiei

  • MUST: Energia = ∑(V * A * Δt) pentru fiecare interval
  • MUST: Unitatea trebuie să fie Wh (Watt-hours)
  • SHOULD: Energia negativă în sesiune = problema în măsurători, loghează warning

Conflict detection și rezoluție

Se declanşează când: 1. Două sesiuni cu aceeași categorie de device în same time window 2. Două sesiuni pe aceeași meter cu overlap temporal

Rezoluţie: - MUST: Sesiunea cu mai multe măsurători = "winner" - MUST: Energiile sunt combinate (∑) - SHOULD: Old session data este archived (Core Data snapshot) - MAY: Notifică utilizator despre merge

State management

  • MUST: Active session nu poate fi schimbat în mod normal (read-only)
  • MUST: State tranzițion: idle → active → completed (nu poate reveni)
  • SHOULD: Completed sesiuni sunt persistent în Core Data

Testare

Unit tests

// Sesiuni
test_startSessionCreatesValidRecord()
test_endSessionCalculatesEnergy()
test_activeSessions_CanOnlyBeOne()
test_sessionTimeValidation()

// Măsurători
test_recordMeasurementFailsIfSessionEnded()
test_measurementsAreOrdered()
test_emptySessionsCalculateZeroEnergy()

// Conflict
test_mergeDetectsDuplicateSessions()
test_mergeKeepsMoreCompleteMeasurements()
test_mergeRecalculates_TotalEnergy()

// Naming
test_renameUpdatesPersistence()

Integration tests

  • [ ] Device apare în Charged Devices list după start sesiune
  • [ ] Sesiuni complete salvate în Core Data
  • [ ] CloudKit sync nu pierde sesiuni
  • [ ] Energiile sunt consistente după conflict merge
  • [ ] Device name e persistent

Dependenţe

  • Meter: conectare şi măsurători
  • ChargeInsightsStore: persistență sesiuni
  • CloudKitSync: replicare iCloud

Notes

Documentaţie asoc: - Charge Session Integrity - No Ampere-Hours in UI