разбор метрик HAE: фикстуры, канонизация, парсер

- tmp/research/fixtures.py собирает фикстуры из архива, вычищая измерения и
  сохраняя порядок ключей, форму литералов, выравнивание меток и невидимые
  символы; шесть фикстур в internal/hae/testdata
- internal/canon — общий дом канонической формы, полноты и хеша: числа читаются
  литералом через json.Number, округление до 12 значащих цифр
- internal/hae — разбор секции metrics, вывод слоя по метрике, разделение схем
  сна, координаты интервалом; recover внутри Parse, фаззинг
- миграция bucket и docs/database.md
This commit is contained in:
av
2026-08-01 17:31:41 +03:00
parent 3e93dd95b4
commit 01d0de59df
18 changed files with 3693 additions and 21 deletions
+45
View File
@@ -0,0 +1,45 @@
# Фикстуры разбора Health Auto Export
Конвенция требует тестов на **реальных** пакетах: документация формата тонкая и
местами расходится с тем, что приложение шлёт на самом деле. Инвариант при этом
запрещает данным о здоровье попадать под контроль версий. Поэтому фикстуры
собраны из живого архива скриптом `tmp/research/fixtures.py`, который сохраняет
всё, на чём работает разбор, и уничтожает всё, что является измерением.
Сохранено дословно: порядок ключей, форма числового литерала, выравнивание
меток по секундам и минутам, смещение зоны, длительности интервалов, невидимые
символы в именах устройств, категориальные значения. Заменено: числа (цифры
переставлены с сохранением формы), даты (сдвинуты на постоянную величину),
имена устройств.
| Файл | Что проверяет |
|---|---|
| `minute.json` | минутная доставка; плотные метрики минутные, одна (`apple_stand_hour`) часовая — классификация **по метрике**, а не по доставке; редкие наследуют минутный слой; суточная сводка сна |
| `hour.json` | часовая доставка целиком |
| `raw.json` | посекундная доставка |
| `mixed.json` | одна доставка с минутными, посекундными и часовыми метриками — перенастройка автоматизации |
| `heartbeat_series.json` | точка с `heartbeatSeries`: третий формат времени, серия проходит исходными байтами |
| `sparse_sleep.json` | доставка **без плотных метрик** (заголовок `Default` не спасает) и поэпизодный сон с задвоенной меткой — интервальная идентичность |
| `handmade_edge.json` | случаи, которых живой поток не даёт (см. ниже) |
`handmade_edge.json` собран руками, скриптом не воспроизводится:
- `mixed_alignment` — плотная метрика, где 10 меток часовые и одна минутная:
слой обязан выйти минутным, потому что слой метрики — **самое мелкое**
встретившееся выравнивание;
- `unknown_shape` — незнакомое поле точки (в том числе вложенное), `1.0`, целое
больше 2⁵³ и дробь длиннее двенадцати значащих цифр: всё это обязано пережить
хранение дословно;
- `broken_timestamps` — RFC 3339 вместо формата HAE, пустая строка, отсутствие
`date` и число вместо строки: каждая точка пропускается со счётчиком, разбор
не падает;
- `interval_points` — три записи с одной меткой и разными интервалами: ключ по
метке схлопнул бы их в одну.
Обновить набор:
```
python3 tmp/research/fixtures.py --list
python3 tmp/research/fixtures.py <файл из data/raw> --metrics a,b --limit 14 \
--out internal/hae/testdata/<имя>.json
```
+78
View File
@@ -0,0 +1,78 @@
{
"_comment": "Рукотворная фикстура: случаи, которых живой поток не даёт. Скриптом tmp/research/fixtures.py не порождается. Значения выдуманы целиком.",
"data": {
"metrics": [
{
"name": "mixed_alignment",
"units": "count",
"data": [
{ "date": "2025-06-05 10:00:00 +0300", "qty": 1, "source": "Device A" },
{ "date": "2025-06-05 11:00:00 +0300", "qty": 2, "source": "Device A" },
{ "date": "2025-06-05 12:00:00 +0300", "qty": 3, "source": "Device A" },
{ "date": "2025-06-05 13:00:00 +0300", "qty": 4, "source": "Device A" },
{ "date": "2025-06-05 14:00:00 +0300", "qty": 5, "source": "Device A" },
{ "date": "2025-06-05 15:00:00 +0300", "qty": 6, "source": "Device A" },
{ "date": "2025-06-05 16:00:00 +0300", "qty": 7, "source": "Device A" },
{ "date": "2025-06-05 17:00:00 +0300", "qty": 8, "source": "Device A" },
{ "date": "2025-06-05 18:00:00 +0300", "qty": 9, "source": "Device A" },
{ "date": "2025-06-05 19:00:00 +0300", "qty": 10, "source": "Device A" },
{ "date": "2025-06-05 19:30:00 +0300", "qty": 11, "source": "Device A" }
]
},
{
"name": "unknown_shape",
"units": "widget",
"data": [
{
"date": "2025-06-05 10:00:00 +0300",
"qty": 1.0,
"hugeInteger": 9007199254740993,
"longFraction": 0.095231829624713534,
"inventedField": { "nested": ["значение", 42], "flag": true },
"source": "Device A"
}
]
},
{
"name": "broken_timestamps",
"units": "count",
"data": [
{ "date": "2025-06-05T10:00:00Z", "qty": 1, "source": "Device A" },
{ "date": "", "qty": 2, "source": "Device A" },
{ "qty": 3, "source": "Device A" },
{ "date": 1749110400, "qty": 4, "source": "Device A" }
]
},
{
"name": "interval_points",
"units": "hr",
"data": [
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-05 22:16:00 +0300",
"qty": 0.2,
"value": "Во сне",
"source": "Device A"
},
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-06 02:21:00 +0300",
"qty": 4.28,
"value": "В кровати",
"source": "Device A"
},
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-06 07:51:00 +0300",
"qty": 9.78,
"value": "В кровати",
"source": "Device A"
}
]
}
]
}
}
+625
View File
@@ -0,0 +1,625 @@
{
"data": {
"metrics": [
{
"data": [
{
"source": "Device A  ",
"qty": 23.750315211285474,
"heartbeatSeries": [
{
"timeSinceStart": 0.30703959892431944,
"date": 4664261259.9741159,
"precededByGap": true
},
{
"timeSinceStart": 7.2309957839083619,
"precededByGap": false,
"date": 4041665251.900013
},
{
"date": 8876178853.342975,
"timeSinceStart": 1.4527448217879887,
"precededByGap": false
},
{
"timeSinceStart": 1.4165263660769081,
"precededByGap": false,
"date": 1000535638.3966900
},
{
"timeSinceStart": 9.0521978531957290,
"date": 9957382189.7722167,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 5.1930893136228618,
"date": 6117853154.6013721
},
{
"timeSinceStart": 6.168269553311381,
"precededByGap": false,
"date": 1745725940.9978662
},
{
"date": 1976712978.903725,
"precededByGap": false,
"timeSinceStart": 2.3069475267343171
},
{
"precededByGap": false,
"timeSinceStart": 5.8297908527491859,
"date": 3587622577.7499014
},
{
"date": 9819293385.3179276,
"precededByGap": false,
"timeSinceStart": 15.188011048333195
},
{
"timeSinceStart": 95.21863539994910,
"date": 1308788664.0329858,
"precededByGap": false
},
{
"timeSinceStart": 64.894156680251802,
"date": 5505628959.0309993,
"precededByGap": false
},
{
"timeSinceStart": 21.161691194935153,
"precededByGap": false,
"date": 6015674224.9529920
},
{
"precededByGap": false,
"timeSinceStart": 55.60822150782505,
"date": 1400661582.8317718
},
{
"date": 3224841469.3113241,
"timeSinceStart": 66.474073083266903,
"precededByGap": false
},
{
"date": 1057590720.8567,
"timeSinceStart": 74.506280415883408,
"precededByGap": false
},
{
"timeSinceStart": 51.567387739757723,
"date": 3963510291.5702180,
"precededByGap": false
},
{
"date": 7082814560.4384724,
"precededByGap": false,
"timeSinceStart": 83.299392816278859
},
{
"date": 6757810417.418241,
"precededByGap": false,
"timeSinceStart": 75.088533409617035
},
{
"precededByGap": false,
"date": 3540114945.8209328,
"timeSinceStart": 56.255259710811021
},
{
"date": 9959500053.3602796,
"timeSinceStart": 43.067500980343614,
"precededByGap": false
},
{
"date": 4426461214.9080886,
"precededByGap": false,
"timeSinceStart": 19.646576005446991
},
{
"timeSinceStart": 81.124503678836476,
"date": 6699644671.7938884,
"precededByGap": false
},
{
"date": 7749707811.2428946,
"precededByGap": false,
"timeSinceStart": 61.227798246118771
},
{
"timeSinceStart": 67.676748577463995,
"date": 6210596381.331694,
"precededByGap": false
},
{
"timeSinceStart": 70.159292660068567,
"date": 7715645840.5534507,
"precededByGap": false
},
{
"timeSinceStart": 92.172251351930605,
"date": 2323554989.0717421,
"precededByGap": false
},
{
"precededByGap": false,
"date": 3886410707.7568370,
"timeSinceStart": 38.86637603495670
},
{
"date": 2657848907.7568171,
"timeSinceStart": 50.485827093291539,
"precededByGap": false
},
{
"date": 2069101105.1355647,
"timeSinceStart": 60.047066360528097,
"precededByGap": false
},
{
"date": 4262931019.7365472,
"precededByGap": false,
"timeSinceStart": 56.760770648554205
},
{
"date": 4457320713.1803937,
"precededByGap": false,
"timeSinceStart": 41.802607769366120
},
{
"precededByGap": false,
"date": 1533078800.0423091,
"timeSinceStart": 49.601596154020277
},
{
"timeSinceStart": 18.441498943378064,
"date": 5980986523.3220126,
"precededByGap": false
},
{
"precededByGap": false,
"date": 7712336863.5983489,
"timeSinceStart": 71.414598926762732
},
{
"precededByGap": false,
"timeSinceStart": 92.4437,
"date": 3514512985.6868826
},
{
"date": 8322478175.1114594,
"precededByGap": false,
"timeSinceStart": 88.6024
},
{
"precededByGap": false,
"timeSinceStart": 29.248195440085157,
"date": 1168676776.9662425
},
{
"timeSinceStart": 79.433379869332866,
"date": 5035752878.088219,
"precededByGap": false
},
{
"date": 1816622784.7747694,
"precededByGap": false,
"timeSinceStart": 75.952011843074849
},
{
"date": 4080028792.2903372,
"timeSinceStart": 53.348069560324092,
"precededByGap": false
},
{
"precededByGap": false,
"date": 1811194281.9697089,
"timeSinceStart": 35.933995598712666
},
{
"date": 8111403588.2629364,
"precededByGap": false,
"timeSinceStart": 40.745484764163
},
{
"timeSinceStart": 72.730211831269887,
"date": 3169688989.3112253,
"precededByGap": false
},
{
"timeSinceStart": 40.986504143982092,
"date": 6527999135.5416463,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 62.331864539823858,
"date": 7385945563.3943794
},
{
"precededByGap": false,
"date": 9921005072.0964865,
"timeSinceStart": 30.064845423262511
},
{
"timeSinceStart": 11.478003936471302,
"date": 1508595739.6221127,
"precededByGap": false
},
{
"date": 5875305221.5406955,
"timeSinceStart": 94.512920953956073,
"precededByGap": false
},
{
"timeSinceStart": 62.149608758072446,
"date": 1457298229.9513884,
"precededByGap": false
},
{
"timeSinceStart": 62.618941135915397,
"precededByGap": false,
"date": 5303487004.6047872
}
],
"date": "2025-06-06 00:16:29 +0300",
"start": "2025-06-06 00:16:29 +0300",
"end": "2025-06-06 00:17:28 +0300"
},
{
"end": "2025-06-06 11:31:35 +0300",
"qty": 90.14058990512054,
"heartbeatSeries": [
{
"precededByGap": true,
"date": 7083484890.61297,
"timeSinceStart": 0.407468
},
{
"date": 1474906531.5871756,
"precededByGap": false,
"timeSinceStart": 5.004982856308269
},
{
"date": 8658903263.1018850,
"timeSinceStart": 1.4807963559238753,
"precededByGap": false
},
{
"timeSinceStart": 1.024701,
"date": 4526622271.20697,
"precededByGap": true
},
{
"timeSinceStart": 2.5091503502811948,
"date": 5019070240.3891780,
"precededByGap": false
},
{
"timeSinceStart": 1.4947476825708789,
"precededByGap": true,
"date": 2436626670.6771267
},
{
"timeSinceStart": 4.2381164797072304,
"date": 7859156077.2136691,
"precededByGap": false
},
{
"timeSinceStart": 1.4840301800760543,
"precededByGap": false,
"date": 3350788867.9988499
},
{
"timeSinceStart": 1.6174706338581461,
"date": 2201781030.1790726,
"precededByGap": false
},
{
"timeSinceStart": 76.362114876750040,
"date": 4956007120.482461,
"precededByGap": false
},
{
"timeSinceStart": 53.631480432828275,
"precededByGap": false,
"date": 9149621715.2385838
},
{
"date": 3715855703.0157515,
"timeSinceStart": 72.497390832000272,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 86.018403315174563,
"date": 4736441058.57521
},
{
"date": 9000957328.1726289,
"precededByGap": false,
"timeSinceStart": 85.838039628007138
},
{
"date": 6576796906.3091040,
"precededByGap": false,
"timeSinceStart": 48.492219341044194
},
{
"timeSinceStart": 10.361132650103484,
"date": 6256615706.247128,
"precededByGap": false
},
{
"timeSinceStart": 29.87069792740100,
"date": 1294004322.690807,
"precededByGap": false
},
{
"date": 1001961220.510529,
"timeSinceStart": 61.39134,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 51.680727012238700,
"date": 1839323959.7726563
},
{
"precededByGap": false,
"date": 3472361417.096725,
"timeSinceStart": 91
},
{
"date": 4826990425.3176300,
"timeSinceStart": 83.619765240667191,
"precededByGap": false
},
{
"timeSinceStart": 10.497349,
"date": 6106959041.51327,
"precededByGap": false
},
{
"timeSinceStart": 71.683393,
"date": 5914109094.15767,
"precededByGap": false
},
{
"date": 8535185762.4824187,
"precededByGap": false,
"timeSinceStart": 77.757778295471486
},
{
"date": 1951867913.0849229,
"timeSinceStart": 67.24866615699993,
"precededByGap": false
},
{
"date": 3290122044.1324209,
"timeSinceStart": 36.193907888310981,
"precededByGap": false
},
{
"timeSinceStart": 41.853869154744907,
"date": 7553108736.6595391,
"precededByGap": true
},
{
"precededByGap": false,
"timeSinceStart": 54.278271967966989,
"date": 3397429066.0191995
},
{
"date": 3383964606.0910157,
"timeSinceStart": 15.374542569216173,
"precededByGap": false
},
{
"precededByGap": false,
"date": 9453909931.5302071,
"timeSinceStart": 70.688961451284457
},
{
"timeSinceStart": 85.5376113915716,
"date": 8527903185.5201554,
"precededByGap": false
},
{
"date": 3833532726.0466381,
"timeSinceStart": 39.325074723044682,
"precededByGap": false
},
{
"timeSinceStart": 51.677835663423346,
"precededByGap": false,
"date": 7096040758.6256057
},
{
"date": 6685143704.3116423,
"precededByGap": false,
"timeSinceStart": 61.04785026
},
{
"date": 9765989645.7654644,
"precededByGap": false,
"timeSinceStart": 15.919857383265833
},
{
"precededByGap": false,
"timeSinceStart": 30.709081717827611,
"date": 2123404262.6558111
},
{
"timeSinceStart": 69.688839940091103,
"date": 7413445159.6479758,
"precededByGap": false
},
{
"date": 5814969011.2566160,
"timeSinceStart": 57.667422028031522,
"precededByGap": false
},
{
"date": 6592553346.0727878,
"precededByGap": false,
"timeSinceStart": 60.47162189527939
},
{
"date": 5587039604.0316581,
"precededByGap": false,
"timeSinceStart": 19.900839099832010
},
{
"date": 4614951959.348113,
"precededByGap": false,
"timeSinceStart": 83.612189839618083
},
{
"precededByGap": false,
"timeSinceStart": 60.161461940965297,
"date": 8112355943.0298539
},
{
"timeSinceStart": 83.782742593829671,
"date": 1484454505.5246212,
"precededByGap": false
},
{
"date": 2959518110.4921864,
"precededByGap": false,
"timeSinceStart": 24.841421745176644
},
{
"precededByGap": false,
"date": 1314440885.0832479,
"timeSinceStart": 64.915260287690918
},
{
"timeSinceStart": 74.170133735782600,
"date": 4031188734.4970767,
"precededByGap": false
},
{
"date": 9123404825.219476,
"precededByGap": false,
"timeSinceStart": 29.865935408801001
},
{
"precededByGap": false,
"timeSinceStart": 38.166543961036381,
"date": 2727966353.3850555
},
{
"date": 2706441390.2806612,
"timeSinceStart": 33.591223332904774,
"precededByGap": false
},
{
"date": 5914992824.6840509,
"timeSinceStart": 83.388875928168685,
"precededByGap": false
},
{
"timeSinceStart": 71.83816912598245,
"date": 1492585088.0453538,
"precededByGap": false
},
{
"timeSinceStart": 69.466728703019153,
"precededByGap": false,
"date": 5894821074.7681045
},
{
"date": 3287835300.1858831,
"timeSinceStart": 22.908710811229499,
"precededByGap": false
},
{
"timeSinceStart": 85.360101931423561,
"date": 5640034746.7509943,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 73.9419,
"date": 1636291248.305578
},
{
"date": 2119560477.3399937,
"precededByGap": false,
"timeSinceStart": 94.668323626933766
},
{
"date": 3271617698.7128734,
"precededByGap": false,
"timeSinceStart": 64.9421751881103
},
{
"date": 1940624563.8133917,
"precededByGap": false,
"timeSinceStart": 88.635802724250809
},
{
"date": 9840541026.4970818,
"precededByGap": false,
"timeSinceStart": 78.314590572727896
},
{
"date": 5491053006.9390733,
"timeSinceStart": 85.769540859478425,
"precededByGap": false
},
{
"precededByGap": false,
"timeSinceStart": 93.473139781209616,
"date": 6535063885.8336494
},
{
"timeSinceStart": 65.146412902364838,
"precededByGap": false,
"date": 2347718058.8244127
},
{
"precededByGap": false,
"timeSinceStart": 11.611609,
"date": 1267561134.54121
},
{
"date": 1195742041.5845607,
"timeSinceStart": 28.889132122802926,
"precededByGap": false
},
{
"date": 1569940739.6020094,
"timeSinceStart": 23.652990950531513,
"precededByGap": false
},
{
"timeSinceStart": 97.519180657346742,
"precededByGap": false,
"date": 7714417592.5918662
},
{
"timeSinceStart": 17.331792299665982,
"precededByGap": false,
"date": 5509625875.398436
},
{
"precededByGap": false,
"timeSinceStart": 63.379430537893649,
"date": 2848110736.6401262
}
],
"start": "2025-06-06 11:30:35 +0300",
"source": "Device A  ",
"date": "2025-06-06 11:30:35 +0300"
}
],
"name": "heart_rate_variability",
"units": "ms"
}
]
}
}
+281
View File
@@ -0,0 +1,281 @@
{
"data": {
"metrics": [
{
"name": "active_energy",
"units": "kJ",
"data": [
{
"qty": 9.0964610089950502,
"date": "2025-06-05 00:00:00 +0300",
"source": "Device A  "
},
{
"date": "2025-06-05 01:00:00 +0300",
"qty": 1.8011831544351500,
"source": "Device A  "
},
{
"qty": 8.3677756683275249,
"source": "Device A  ",
"date": "2025-06-05 02:00:00 +0300"
},
{
"source": "Device A  ",
"qty": 3.3985452404807405,
"date": "2025-06-05 03:00:00 +0300"
},
{
"qty": 12.618722903999360,
"date": "2025-06-05 04:00:00 +0300",
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-05 05:00:00 +0300",
"qty": 40.351034546189656
},
{
"source": "Device A  ",
"qty": 6.507009541624532,
"date": "2025-06-05 06:00:00 +0300"
},
{
"date": "2025-06-06 06:00:00 +0300",
"qty": 55.821611193078514,
"source": "Device A  "
},
{
"qty": 2.295029103054565,
"date": "2025-06-06 07:00:00 +0300",
"source": "Device A  "
},
{
"date": "2025-06-06 08:00:00 +0300",
"qty": 322.8983115506521,
"source": "Device A  "
},
{
"qty": 91.588676831471213,
"date": "2025-06-06 09:00:00 +0300",
"source": "Device A  "
},
{
"qty": 462.61760657433137,
"source": "Device A  ",
"date": "2025-06-06 10:00:00 +0300"
},
{
"date": "2025-06-06 11:00:00 +0300",
"qty": 958.07555299152843,
"source": "Device A  "
},
{
"qty": 67.473524552265953,
"source": "Device A  ",
"date": "2025-06-06 12:00:00 +0300"
}
]
},
{
"units": "hr",
"data": [
{
"core": 6.2052788381114499,
"inBedEnd": "2025-06-05 05:22:26 +0300",
"date": "2025-06-05 00:00:00 +0300",
"inBed": 0,
"rem": 0.89195271872064281,
"sleepEnd": "2025-06-05 05:22:26 +0300",
"source": "Device A  ",
"totalSleep": 4.0716939170300220,
"inBedStart": "2025-06-04 22:34:34 +0300",
"asleep": 0,
"awake": 4.3396901109717361,
"sleepStart": "2025-06-04 22:34:34 +0300",
"deep": 0.68835541253715609
},
{
"awake": 9.638151247778914,
"inBed": 0,
"deep": 0.38341974910703597,
"inBedStart": "2025-06-05 22:43:20 +0300",
"rem": 0.43532011302795238,
"sleepEnd": "2025-06-06 07:57:39 +0300",
"date": "2025-06-06 00:00:00 +0300",
"core": 5.152708504451071,
"source": "Device A  ",
"asleep": 0,
"sleepStart": "2025-06-05 22:43:20 +0300",
"inBedEnd": "2025-06-06 07:57:39 +0300",
"totalSleep": 4.4003075324079272
}
],
"name": "sleep_analysis"
},
{
"name": "apple_stand_hour",
"data": [
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 07:00:00 +0300"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 08:00:00 +0300"
},
{
"date": "2025-06-05 09:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"source": "Device A",
"date": "2025-06-05 10:00:00 +0300",
"qty": 8
},
{
"source": "Device A",
"date": "2025-06-05 12:00:00 +0300",
"qty": 8
},
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 13:00:00 +0300"
},
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 15:00:00 +0300"
},
{
"qty": 8,
"date": "2025-06-05 20:00:00 +0300",
"source": "Device A"
},
{
"date": "2025-06-05 21:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"date": "2025-06-06 02:00:00 +0300",
"source": "Device A",
"qty": 8
},
{
"qty": 8,
"source": "Device A",
"date": "2025-06-06 08:00:00 +0300"
},
{
"date": "2025-06-06 09:00:00 +0300",
"source": "Device A",
"qty": 8
},
{
"date": "2025-06-06 10:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"source": "Device A",
"date": "2025-06-06 11:00:00 +0300",
"qty": 8
}
],
"units": "count"
},
{
"units": "ms",
"data": [
{
"date": "2025-06-05 00:00:00 +0300",
"qty": 51.209189787471513,
"source": "Device A  "
},
{
"date": "2025-06-05 02:00:00 +0300",
"source": "Device A  ",
"qty": 62.091594303847203
},
{
"date": "2025-06-05 04:00:00 +0300",
"qty": 496.11595771813635,
"source": "Device A  "
},
{
"qty": 89.502763665053950,
"source": "Device A  ",
"date": "2025-06-05 06:00:00 +0300"
},
{
"source": "Device A  ",
"qty": 15.145830153758666,
"date": "2025-06-05 08:00:00 +0300"
},
{
"source": "Device A  ",
"date": "2025-06-05 10:00:00 +0300",
"qty": 96.442927435831922
},
{
"date": "2025-06-05 12:00:00 +0300",
"qty": 16.490675484303301,
"source": "Device A  "
},
{
"date": "2025-06-05 22:00:00 +0300",
"source": "Device A  ",
"qty": 25.801867024959922
},
{
"date": "2025-06-06 00:00:00 +0300",
"qty": 23.750315211285474,
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-06 02:00:00 +0300",
"qty": 21.676280750344913
},
{
"qty": 108.159159427689,
"date": "2025-06-06 04:00:00 +0300",
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-06 06:00:00 +0300",
"qty": 14.548300046808019
},
{
"qty": 22.843350035832434,
"date": "2025-06-06 08:00:00 +0300",
"source": "Device A  "
},
{
"date": "2025-06-06 11:00:00 +0300",
"qty": 90.14058990512054,
"source": "Device A  "
}
],
"name": "heart_rate_variability"
},
{
"data": [
{
"qty": 745,
"source": "Device A",
"date": "2025-06-05 05:00:00 +0300"
}
],
"units": "m",
"name": "six_minute_walking_test_distance"
}
]
}
}
+281
View File
@@ -0,0 +1,281 @@
{
"data": {
"metrics": [
{
"units": "hr",
"data": [
{
"rem": 0.89195271872064281,
"inBed": 0,
"awake": 4.3396901109717361,
"deep": 0.68835541253715609,
"asleep": 0,
"totalSleep": 4.0716939170300220,
"source": "Device A  ",
"core": 6.2052788381114499,
"inBedStart": "2025-06-04 22:34:34 +0300",
"sleepEnd": "2025-06-05 05:22:26 +0300",
"inBedEnd": "2025-06-05 05:22:26 +0300",
"date": "2025-06-05 00:00:00 +0300",
"sleepStart": "2025-06-04 22:34:34 +0300"
},
{
"inBedStart": "2025-06-05 22:43:20 +0300",
"deep": 0.38341974910703597,
"rem": 0.43532011302795238,
"core": 5.152708504451071,
"date": "2025-06-06 00:00:00 +0300",
"inBed": 0,
"inBedEnd": "2025-06-06 07:57:39 +0300",
"asleep": 0,
"source": "Device A  ",
"sleepStart": "2025-06-05 22:43:20 +0300",
"awake": 9.638151247778914,
"sleepEnd": "2025-06-06 07:57:39 +0300",
"totalSleep": 4.4003075324079272
}
],
"name": "sleep_analysis"
},
{
"name": "apple_stand_hour",
"data": [
{
"source": "Device A",
"date": "2025-06-05 07:00:00 +0300",
"qty": 8
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 08:00:00 +0300"
},
{
"qty": 8,
"date": "2025-06-05 09:00:00 +0300",
"source": "Device A"
},
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 10:00:00 +0300"
},
{
"source": "Device A",
"date": "2025-06-05 12:00:00 +0300",
"qty": 8
},
{
"source": "Device A",
"date": "2025-06-05 13:00:00 +0300",
"qty": 8
},
{
"date": "2025-06-05 15:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 19:00:00 +0300"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 20:00:00 +0300"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 21:00:00 +0300"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-06 02:00:00 +0300"
},
{
"source": "Device A",
"date": "2025-06-06 08:00:00 +0300",
"qty": 8
},
{
"qty": 8,
"date": "2025-06-06 09:00:00 +0300",
"source": "Device A"
},
{
"source": "Device A",
"date": "2025-06-06 10:00:00 +0300",
"qty": 8
}
],
"units": "count"
},
{
"units": "kJ",
"name": "active_energy",
"data": [
{
"qty": 0.94633004162661996,
"source": "Device A  ",
"date": "2025-06-05 00:24:00 +0300"
},
{
"source": "Device A  ",
"date": "2025-06-05 00:25:00 +0300",
"qty": 0.22385813552875930
},
{
"source": "Device A  ",
"date": "2025-06-05 00:26:00 +0300",
"qty": 0.22385813552875930
},
{
"source": "Device A  ",
"date": "2025-06-05 00:27:00 +0300",
"qty": 0.27046667301884517
},
{
"qty": 0.23659841288096517,
"date": "2025-06-05 00:28:00 +0300",
"source": "Device A  "
},
{
"qty": 0.23659841288096517,
"source": "Device A  ",
"date": "2025-06-05 00:29:00 +0300"
},
{
"source": "Device A  ",
"qty": 0.23659841288096517,
"date": "2025-06-05 00:30:00 +0300"
},
{
"qty": 4.3538077885409284,
"source": "Device A  ",
"date": "2025-06-06 11:47:00 +0300"
},
{
"date": "2025-06-06 11:48:00 +0300",
"qty": 4.3538077885409284,
"source": "Device A  "
},
{
"date": "2025-06-06 11:49:00 +0300",
"qty": 4.3538077885409284,
"source": "Device A  "
},
{
"date": "2025-06-06 11:50:00 +0300",
"source": "Device A  ",
"qty": 2.1847867270334114
},
{
"date": "2025-06-06 11:51:00 +0300",
"qty": 2.1847867270334114,
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-06 11:52:00 +0300",
"qty": 3.3347070079576802
},
{
"source": "Device A  ",
"date": "2025-06-06 11:53:00 +0300",
"qty": 0.96620370889283594
}
]
},
{
"data": [
{
"qty": 51.209189787471513,
"source": "Device A  ",
"date": "2025-06-05 00:16:00 +0300"
},
{
"date": "2025-06-05 02:16:00 +0300",
"source": "Device A  ",
"qty": 62.091594303847203
},
{
"qty": 496.11595771813635,
"date": "2025-06-05 04:16:00 +0300",
"source": "Device A  "
},
{
"date": "2025-06-05 06:16:00 +0300",
"qty": 89.502763665053950,
"source": "Device A  "
},
{
"date": "2025-06-05 08:16:00 +0300",
"source": "Device A  ",
"qty": 15.145830153758666
},
{
"date": "2025-06-05 10:16:00 +0300",
"source": "Device A  ",
"qty": 96.442927435831922
},
{
"date": "2025-06-05 12:20:00 +0300",
"qty": 16.490675484303301,
"source": "Device A  "
},
{
"date": "2025-06-05 22:19:00 +0300",
"qty": 25.801867024959922,
"source": "Device A  "
},
{
"qty": 23.750315211285474,
"source": "Device A  ",
"date": "2025-06-06 00:16:00 +0300"
},
{
"qty": 21.676280750344913,
"date": "2025-06-06 02:16:00 +0300",
"source": "Device A  "
},
{
"date": "2025-06-06 04:16:00 +0300",
"source": "Device A  ",
"qty": 108.159159427689
},
{
"date": "2025-06-06 06:16:00 +0300",
"qty": 14.548300046808019,
"source": "Device A  "
},
{
"source": "Device A  ",
"qty": 22.843350035832434,
"date": "2025-06-06 08:16:00 +0300"
},
{
"date": "2025-06-06 11:30:00 +0300",
"source": "Device A  ",
"qty": 90.14058990512054
}
],
"units": "ms",
"name": "heart_rate_variability"
},
{
"name": "six_minute_walking_test_distance",
"units": "m",
"data": [
{
"date": "2025-06-05 05:46:00 +0300",
"source": "Device A",
"qty": 745
}
]
}
]
}
}
+314
View File
@@ -0,0 +1,314 @@
{
"data": {
"metrics": [
{
"name": "apple_stand_hour",
"units": "count",
"data": [
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 07:00:00 +0300"
},
{
"source": "Device A",
"date": "2025-06-05 08:00:00 +0300",
"qty": 8
},
{
"date": "2025-06-05 09:00:00 +0300",
"source": "Device A",
"qty": 8
},
{
"date": "2025-06-05 10:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-05 12:00:00 +0300"
},
{
"qty": 8,
"date": "2025-06-05 13:00:00 +0300",
"source": "Device A"
},
{
"qty": 8,
"date": "2025-06-05 15:00:00 +0300",
"source": "Device A"
},
{
"qty": 8,
"date": "2025-06-05 19:00:00 +0300",
"source": "Device A"
},
{
"qty": 8,
"source": "Device A",
"date": "2025-06-05 20:00:00 +0300"
},
{
"date": "2025-06-05 21:00:00 +0300",
"source": "Device A",
"qty": 8
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-06 02:00:00 +0300"
},
{
"date": "2025-06-06 08:00:00 +0300",
"source": "Device A",
"qty": 8
},
{
"date": "2025-06-06 09:00:00 +0300",
"qty": 8,
"source": "Device A"
},
{
"source": "Device A",
"qty": 8,
"date": "2025-06-06 10:00:00 +0300"
}
]
},
{
"units": "hr",
"data": [
{
"sleepEnd": "2025-06-05 05:22:26 +0300",
"inBedStart": "2025-06-04 22:34:34 +0300",
"core": 6.2052788381114499,
"rem": 0.89195271872064281,
"date": "2025-06-05 00:00:00 +0300",
"totalSleep": 4.0716939170300220,
"sleepStart": "2025-06-04 22:34:34 +0300",
"awake": 4.3396901109717361,
"inBed": 0,
"deep": 0.68835541253715609,
"source": "Device A  ",
"inBedEnd": "2025-06-05 05:22:26 +0300",
"asleep": 0
},
{
"source": "Device A  ",
"date": "2025-06-06 00:00:00 +0300",
"asleep": 0,
"core": 5.152708504451071,
"inBed": 0,
"totalSleep": 4.4003075324079272,
"rem": 0.43532011302795238,
"inBedEnd": "2025-06-06 07:57:39 +0300",
"sleepStart": "2025-06-05 22:43:20 +0300",
"awake": 9.638151247778914,
"deep": 0.38341974910703597,
"sleepEnd": "2025-06-06 07:57:39 +0300",
"inBedStart": "2025-06-05 22:43:20 +0300"
}
],
"name": "sleep_analysis"
},
{
"units": "kJ",
"name": "active_energy",
"data": [
{
"source": "Device A  ",
"qty": 0.94633004162661996,
"date": "2025-06-05 00:24:00 +0300"
},
{
"date": "2025-06-05 00:25:00 +0300",
"source": "Device A  ",
"qty": 0.22385813552875930
},
{
"source": "Device A  ",
"date": "2025-06-05 00:26:00 +0300",
"qty": 0.22385813552875930
},
{
"qty": 0.27046667301884517,
"source": "Device A  ",
"date": "2025-06-05 00:27:00 +0300"
},
{
"date": "2025-06-05 00:28:00 +0300",
"qty": 0.23659841288096517,
"source": "Device A  "
},
{
"qty": 0.23659841288096517,
"date": "2025-06-05 00:29:00 +0300",
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-05 00:30:00 +0300",
"qty": 0.23659841288096517
},
{
"date": "2025-06-06 11:47:00 +0300",
"source": "Device A  ",
"qty": 4.3538077885409284
},
{
"source": "Device A  ",
"date": "2025-06-06 11:48:00 +0300",
"qty": 4.3538077885409284
},
{
"date": "2025-06-06 11:49:00 +0300",
"qty": 4.3538077885409284,
"source": "Device A  "
},
{
"date": "2025-06-06 11:50:00 +0300",
"source": "Device A  ",
"qty": 2.1847867270334114
},
{
"source": "Device A  ",
"qty": 2.1847867270334114,
"date": "2025-06-06 11:51:00 +0300"
},
{
"date": "2025-06-06 11:52:00 +0300",
"source": "Device A  ",
"qty": 3.3347070079576802
},
{
"qty": 0.96620370889283594,
"date": "2025-06-06 11:53:00 +0300",
"source": "Device A  "
}
]
},
{
"data": [
{
"date": "2025-06-05 00:00:00 +0300",
"qty": 96,
"source": "Device A  "
},
{
"source": "Device A  ",
"date": "2025-06-06 00:02:00 +0300",
"qty": 60
}
],
"name": "resting_heart_rate",
"units": "count/min"
},
{
"units": "count/min",
"data": [
{
"Min": 67,
"date": "2025-06-05 00:00:53 +0300",
"source": "Device A  ",
"Avg": 67,
"Max": 67
},
{
"source": "Device A  ",
"Avg": 18,
"Min": 18,
"date": "2025-06-05 00:02:37 +0300",
"Max": 18
},
{
"Max": 18,
"date": "2025-06-05 00:05:25 +0300",
"source": "Device A  |Device B",
"Min": 18,
"Avg": 18
},
{
"date": "2025-06-05 00:11:01 +0300",
"source": "Device A  |Device B",
"Max": 18,
"Min": 18,
"Avg": 18
},
{
"date": "2025-06-05 00:12:30 +0300",
"Min": 18,
"Avg": 18,
"source": "Device A  |Device B",
"Max": 18
},
{
"Max": 82.669907989920684,
"Min": 82.669907989920684,
"Avg": 82.669907989920684,
"source": "Device A  |Device B",
"date": "2025-06-05 00:16:36 +0300"
},
{
"Avg": 67,
"source": "Device A  |Device B",
"Max": 67,
"date": "2025-06-05 00:18:54 +0300",
"Min": 67
},
{
"date": "2025-06-06 11:30:12 +0300",
"Max": 33,
"Min": 33,
"source": "Device A  |Device B",
"Avg": 33
},
{
"date": "2025-06-06 11:30:20 +0300",
"source": "Device A  |Device B",
"Max": 88,
"Min": 88,
"Avg": 88
},
{
"Avg": 37.044306705474884,
"date": "2025-06-06 11:30:35 +0300",
"source": "Device A  |Device B",
"Max": 37.044306705474884,
"Min": 37.044306705474884
},
{
"date": "2025-06-06 11:33:33 +0300",
"Min": 33,
"source": "Device A  |Device B",
"Max": 33,
"Avg": 33
},
{
"source": "Device A  |Device B",
"Avg": 16,
"date": "2025-06-06 11:36:55 +0300",
"Min": 16,
"Max": 16
},
{
"Min": 45,
"date": "2025-06-06 11:44:45 +0300",
"source": "Device A  |Device B",
"Max": 45,
"Avg": 45
},
{
"Avg": 64,
"date": "2025-06-06 11:51:40 +0300",
"Max": 64,
"source": "Device A  |Device B",
"Min": 64
}
],
"name": "heart_rate"
}
]
}
}
+163
View File
@@ -0,0 +1,163 @@
{
"data": {
"metrics": [
{
"data": [
{
"source": "Device A  ",
"qty": 60,
"date": "2025-06-06 00:02:07 +0300",
"start": "2025-06-06 00:02:07 +0300",
"end": "2025-06-06 11:51:40 +0300"
}
],
"name": "resting_heart_rate",
"units": "count/min"
},
{
"name": "heart_rate",
"units": "count/min",
"data": [
{
"Min": 71,
"source": "Device A  ",
"Avg": 71,
"date": "2025-06-06 00:02:07 +0300",
"start": "2025-06-06 00:02:07 +0300",
"context": "Не задано",
"Max": 71,
"end": "2025-06-06 00:02:07 +0300"
},
{
"start": "2025-06-06 00:05:48 +0300",
"date": "2025-06-06 00:05:48 +0300",
"end": "2025-06-06 00:05:48 +0300",
"Max": 31,
"source": "Device A",
"Min": 31,
"Avg": 31
},
{
"source": "Device A  ",
"Min": 18,
"Max": 18,
"end": "2025-06-06 00:06:54 +0300",
"start": "2025-06-06 00:06:54 +0300",
"Avg": 18,
"date": "2025-06-06 00:06:54 +0300",
"context": "Не задано"
},
{
"context": "Не задано",
"Avg": 67,
"Max": 67,
"start": "2025-06-06 00:13:52 +0300",
"end": "2025-06-06 00:13:52 +0300",
"Min": 67,
"source": "Device A  ",
"date": "2025-06-06 00:13:52 +0300"
},
{
"source": "Device A  ",
"start": "2025-06-06 00:16:29 +0300",
"Min": 57.120105773170690,
"context": "Не задано",
"Max": 57.120105773170690,
"Avg": 57.120105773170690,
"date": "2025-06-06 00:16:29 +0300",
"end": "2025-06-06 00:16:29 +0300"
},
{
"Avg": 67,
"start": "2025-06-06 00:18:17 +0300",
"Min": 67,
"date": "2025-06-06 00:18:17 +0300",
"Max": 67,
"source": "Device A  ",
"end": "2025-06-06 00:18:17 +0300",
"context": "Не задано"
},
{
"Avg": 18,
"end": "2025-06-06 00:26:32 +0300",
"date": "2025-06-06 00:26:32 +0300",
"context": "Не задано",
"start": "2025-06-06 00:26:32 +0300",
"source": "Device A  ",
"Max": 18,
"Min": 18
},
{
"Avg": 33,
"Max": 33,
"Min": 33,
"context": "Сидячий образ жизни",
"date": "2025-06-06 11:30:12 +0300",
"start": "2025-06-06 11:30:12 +0300",
"source": "Device A  ",
"end": "2025-06-06 11:30:12 +0300"
},
{
"start": "2025-06-06 11:30:20 +0300",
"source": "Device A",
"Min": 88,
"Avg": 88,
"end": "2025-06-06 11:30:20 +0300",
"Max": 88,
"date": "2025-06-06 11:30:20 +0300"
},
{
"date": "2025-06-06 11:30:35 +0300",
"end": "2025-06-06 11:30:35 +0300",
"Avg": 37.044306705474884,
"Max": 37.044306705474884,
"start": "2025-06-06 11:30:35 +0300",
"source": "Device A  ",
"context": "Не задано",
"Min": 37.044306705474884
},
{
"source": "Device A  ",
"context": "Сидячий образ жизни",
"date": "2025-06-06 11:33:33 +0300",
"Max": 33,
"Min": 33,
"end": "2025-06-06 11:33:33 +0300",
"Avg": 33,
"start": "2025-06-06 11:33:33 +0300"
},
{
"date": "2025-06-06 11:36:55 +0300",
"start": "2025-06-06 11:36:55 +0300",
"Avg": 16,
"Max": 16,
"Min": 16,
"context": "Сидячий образ жизни",
"source": "Device A  ",
"end": "2025-06-06 11:36:55 +0300"
},
{
"Min": 45,
"Avg": 45,
"context": "Сидячий образ жизни",
"source": "Device A  ",
"Max": 45,
"start": "2025-06-06 11:44:45 +0300",
"end": "2025-06-06 11:44:45 +0300",
"date": "2025-06-06 11:44:45 +0300"
},
{
"source": "Device A  ",
"Avg": 64,
"context": "Сидячий образ жизни",
"Max": 64,
"Min": 64,
"end": "2025-06-06 11:51:40 +0300",
"start": "2025-06-06 11:51:40 +0300",
"date": "2025-06-06 11:51:40 +0300"
}
]
}
]
}
}
+78
View File
@@ -0,0 +1,78 @@
{
"data": {
"metrics": [
{
"data": [
{
"qty": 0.48052029446490479,
"value": "Во сне",
"source": "Device A",
"start": "2025-06-05 22:04:00 +0300",
"startDate": "2025-06-05 22:04:00 +0300",
"endDate": "2025-06-05 22:16:00 +0300",
"end": "2025-06-05 22:16:00 +0300",
"date": "2025-06-05 22:04:00 +0300"
},
{
"endDate": "2025-06-06 02:21:00 +0300",
"qty": 1.5130355381745861,
"startDate": "2025-06-05 22:04:00 +0300",
"date": "2025-06-05 22:04:00 +0300",
"value": "В кровати",
"source": "Device A",
"end": "2025-06-06 02:21:00 +0300",
"start": "2025-06-05 22:04:00 +0300"
},
{
"qty": 9.1550074802731359,
"source": "Device A",
"end": "2025-06-06 01:26:00 +0300",
"value": "Во сне",
"start": "2025-06-05 22:40:00 +0300",
"startDate": "2025-06-05 22:40:00 +0300",
"date": "2025-06-05 22:40:00 +0300",
"endDate": "2025-06-06 01:26:00 +0300"
},
{
"date": "2025-06-06 01:27:00 +0300",
"endDate": "2025-06-06 02:21:00 +0300",
"qty": 0.78349523542270867,
"end": "2025-06-06 02:21:00 +0300",
"source": "Device A",
"value": "Во сне",
"start": "2025-06-06 01:27:00 +0300",
"startDate": "2025-06-06 01:27:00 +0300"
}
],
"units": "hr",
"name": "sleep_analysis"
},
{
"name": "heart_rate",
"units": "count/min",
"data": [
{
"context": "Не задано",
"Max": 31,
"date": "2025-06-06 03:00:36 +0300",
"start": "2025-06-06 03:00:36 +0300",
"Avg": 31,
"source": "Device A  ",
"Min": 31,
"end": "2025-06-06 03:00:36 +0300"
},
{
"Min": 12,
"source": "Device A  ",
"start": "2025-06-06 03:04:20 +0300",
"date": "2025-06-06 03:04:20 +0300",
"Max": 12,
"Avg": 12,
"context": "Не задано",
"end": "2025-06-06 03:04:20 +0300"
}
]
}
]
}
}