16
16
#include < QJsonObject>
17
17
#include < QJsonValue>
18
18
#include < QSettings>
19
+ #include < QTimer>
19
20
#include < deconz/atom_table.h>
20
21
#include < deconz/dbg_trace.h>
21
22
#include < deconz/file.h>
@@ -106,9 +107,14 @@ struct ConstantEntry
106
107
enum DDF_LoadState
107
108
{
108
109
DDF_LoadStateScheduled,
109
- DDF_LoadStateNotFound,
110
- DDF_LoadStateLoadedRawJson,
111
- DDF_LoadStateLoadedBundle
110
+ DDF_LoadStateLoaded
111
+ };
112
+
113
+ enum DDF_ReloadWhat
114
+ {
115
+ DDF_ReloadIdle,
116
+ DDF_ReloadBundles,
117
+ DDF_ReloadAll
112
118
};
113
119
114
120
struct DDF_LoadRecord
@@ -141,6 +147,9 @@ class DeviceDescriptionsPrivate
141
147
142
148
std::vector<DDF_LoadRecord> ddfLoadRecords;
143
149
std::vector<U_ECC_PublicKeySecp256k1> publicKeys;
150
+
151
+ DDF_ReloadWhat ddfReloadWhat = DDF_ReloadIdle;
152
+ QTimer *ddfReloadTimer = nullptr ;
144
153
};
145
154
146
155
static int DDF_ReadFileInMemory (DDF_ParseContext *pctx);
@@ -165,6 +174,9 @@ DeviceDescriptions::DeviceDescriptions(QObject *parent) :
165
174
_instance = this ;
166
175
_priv = d_ptr2;
167
176
177
+ d_ptr2->ddfReloadTimer = new QTimer (this );
178
+ d_ptr2->ddfReloadTimer ->setSingleShot (true );
179
+ connect (d_ptr2->ddfReloadTimer , &QTimer::timeout, this , &DeviceDescriptions::ddfReloadTimerFired);
168
180
169
181
{
170
182
// register DDF policy atoms used later on for fast comparisons
@@ -1024,7 +1036,6 @@ void DeviceDescriptions::handleEvent(const Event &event)
1024
1036
{
1025
1037
if (event.num () == 0 )
1026
1038
{
1027
- readAll (); // todo read only device specific files?
1028
1039
}
1029
1040
}
1030
1041
}
@@ -1984,7 +1995,7 @@ void DeviceDescriptions::readAllRawJson()
1984
1995
1985
1996
std::vector<DDF_SubDeviceDescriptor> subDevices;
1986
1997
1987
- std::array<deCONZ::StorageLocation, 2 > locations = { deCONZ::DdfUserLocation , deCONZ::DdfLocation };
1998
+ std::array<deCONZ::StorageLocation, 2 > locations = { deCONZ::DdfLocation , deCONZ::DdfUserLocation };
1988
1999
1989
2000
for (size_t dit = 0 ; dit < locations.size (); dit++)
1990
2001
{
@@ -2135,15 +2146,10 @@ void DeviceDescriptions::readAllRawJson()
2135
2146
2136
2147
for (k = 0 ; k < d->ddfLoadRecords .size (); k++)
2137
2148
{
2138
- if (d->ddfLoadRecords [k].loadState != DDF_LoadStateScheduled)
2139
- {
2140
- continue ;
2141
- }
2142
-
2143
2149
if (mfnameIndex.index == d->ddfLoadRecords [k].mfname .index &&
2144
2150
modelidIndex.index == d->ddfLoadRecords [k].modelid .index )
2145
2151
{
2146
- d->ddfLoadRecords [k].loadState = DDF_LoadStateLoadedRawJson;
2152
+ // d->ddfLoadRecords[k].loadState = DDF_LoadStateLoadedRawJson;
2147
2153
scheduled = true ;
2148
2154
break ;
2149
2155
}
@@ -2267,6 +2273,7 @@ static int DDF_ReloadBundleDevices(const char *desc, unsigned descSize, std::vec
2267
2273
AT_AtomIndex mfname_ati;
2268
2274
cj_token *tokens;
2269
2275
unsigned n_tokens = 1024 ;
2276
+ int n_marked = 0 ;
2270
2277
2271
2278
ScratchMemWaypoint swp;
2272
2279
tokens = SCRATCH_ALLOC (cj_token*, n_tokens * sizeof (*tokens));
@@ -2341,20 +2348,23 @@ static int DDF_ReloadBundleDevices(const char *desc, unsigned descSize, std::vec
2341
2348
2342
2349
for (size_t j = 0 ; j < ddfLoadRecords.size (); j++)
2343
2350
{
2344
- const DDF_LoadRecord &rec = ddfLoadRecords[j];
2351
+ DDF_LoadRecord &rec = ddfLoadRecords[j];
2345
2352
2346
2353
if (rec.mfname .index != mfname_ati.index )
2347
2354
continue ;
2348
2355
2349
2356
if (rec.modelid .index != modelid_ati.index )
2350
2357
continue ;
2351
2358
2352
- // trigger DDF reload event for matching devices
2353
- DEV_ReloadDeviceIdendifier (mfname_ati.index , modelid_ati.index );
2359
+ if (rec.loadState != DDF_LoadStateScheduled)
2360
+ {
2361
+ rec.loadState = DDF_LoadStateScheduled;
2362
+ n_marked++;
2363
+ }
2354
2364
}
2355
2365
}
2356
2366
2357
- return 1 ;
2367
+ return n_marked > 0 ;
2358
2368
}
2359
2369
2360
2370
static int DDF_IsBundleScheduled (DDF_ParseContext *pctx, const char *desc, unsigned descSize, const std::vector<DDF_LoadRecord> &ddfLoadRecords)
@@ -2479,8 +2489,65 @@ void DEV_DDF_BundleUpdated(unsigned char *data, unsigned dataSize)
2479
2489
if (DDFB_FindChunk (&bs, " DESC" , &chunkSize) == 0 )
2480
2490
return ;
2481
2491
2482
- _instance->readAllBundles (); // this is a bit hard core, but does the job for now
2483
- DDF_ReloadBundleDevices ((char *)&bs.data [bs.pos ], chunkSize, _priv->ddfLoadRecords );
2492
+ if (DDF_ReloadBundleDevices ((char *)&bs.data [bs.pos ], chunkSize, _priv->ddfLoadRecords ) != 0 )
2493
+ {
2494
+ _priv->ddfReloadWhat = DDF_ReloadBundles;
2495
+ _priv->ddfReloadTimer ->stop ();
2496
+ _priv->ddfReloadTimer ->start (2000 );
2497
+ }
2498
+ }
2499
+
2500
+ void DeviceDescriptions::reloadAllRawJsonAndBundles (const Resource *resource)
2501
+ {
2502
+
2503
+ const ResourceItem *mfnameItem = resource->item (RAttrManufacturerName);
2504
+ const ResourceItem *modelidItem = resource->item (RAttrModelId);
2505
+ unsigned mfnameAtomIndex = mfnameItem->atomIndex ();
2506
+ unsigned modelidAtomIndex = modelidItem->atomIndex ();
2507
+
2508
+ for (size_t j = 0 ; j < d_ptr2->ddfLoadRecords .size (); j++)
2509
+ {
2510
+ DDF_LoadRecord &rec = d_ptr2->ddfLoadRecords [j];
2511
+
2512
+ if (rec.mfname .index != mfnameAtomIndex)
2513
+ continue ;
2514
+
2515
+ if (rec.modelid .index != modelidAtomIndex)
2516
+ continue ;
2517
+
2518
+ if (rec.loadState != DDF_LoadStateScheduled)
2519
+ {
2520
+ rec.loadState = DDF_LoadStateScheduled;
2521
+ }
2522
+ }
2523
+
2524
+ d_ptr2->ddfReloadWhat = DDF_ReloadAll;
2525
+ d_ptr2->ddfReloadTimer ->stop ();
2526
+ d_ptr2->ddfReloadTimer ->start (1000 );
2527
+ }
2528
+
2529
+ void DeviceDescriptions::ddfReloadTimerFired ()
2530
+ {
2531
+ if (d_ptr2->ddfReloadWhat == DDF_ReloadAll)
2532
+ {
2533
+ readAll ();
2534
+ }
2535
+ else if (d_ptr2->ddfReloadWhat == DDF_ReloadBundles)
2536
+ {
2537
+ readAllBundles ();
2538
+ }
2539
+
2540
+ d_ptr2->ddfReloadWhat = DDF_ReloadIdle;
2541
+
2542
+ for (DDF_LoadRecord &rec : d_ptr2->ddfLoadRecords )
2543
+ {
2544
+ // trigger DDF reload event for matching devices
2545
+ if (rec.loadState == DDF_LoadStateScheduled)
2546
+ {
2547
+ rec.loadState = DDF_LoadStateLoaded;
2548
+ DEV_ReloadDeviceIdendifier (rec.mfname .index , rec.modelid .index );
2549
+ }
2550
+ }
2484
2551
}
2485
2552
2486
2553
/* ! Reads all scheduled DDF bundles.
@@ -2789,6 +2856,32 @@ void DeviceDescriptions::handleDDFInitRequest(const Event &event)
2789
2856
2790
2857
if (DEV_InitBaseDescriptionForDevice (device, ddf1))
2791
2858
{
2859
+ /*
2860
+ * Register all atoms for faster lookups.
2861
+ */
2862
+ for (const auto &mfname : ddf1.manufacturerNames )
2863
+ {
2864
+ const QString m = constantToString (mfname);
2865
+
2866
+ AT_AtomIndex ati;
2867
+ if (AT_AddAtom (m.toUtf8 ().data (), m.size (), &ati) && ati.index != 0 )
2868
+ {
2869
+ ddf1.mfnameAtomIndices .push_back (ati.index );
2870
+ }
2871
+ }
2872
+
2873
+ for (const auto &modelId : ddf1.modelIds )
2874
+ {
2875
+ const QString m = constantToString (modelId);
2876
+
2877
+ AT_AtomIndex ati;
2878
+ if (AT_AddAtom (m.toUtf8 ().data (), m.size (), &ati) && ati.index != 0 )
2879
+ {
2880
+ ddf1.modelidAtomIndices .push_back (ati.index );
2881
+ }
2882
+ }
2883
+
2884
+ ddf1.storageLocation = deCONZ::DdfUserLocation;
2792
2885
d->descriptions .push_back (std::move (ddf1));
2793
2886
DDF_UpdateItemHandlesForIndex (d->descriptions , d->loadCounter , d->descriptions .size () - 1 );
2794
2887
}
0 commit comments