@@ -51,6 +51,7 @@ type subscription = interface {
5151type Config struct {
5252 DeviceCacheExpirationSeconds int64
5353 ObserverPollingIntervalSeconds uint64 // 0 means 3 seconds
54+ ObserverFailureThreshold uint8 // 0 means 3
5455
5556 KeepAliveConnectionTimeoutSeconds uint64 // 0 means keepalive is disabled
5657 MaxMessageSize uint32
@@ -140,37 +141,144 @@ func NewClientFromConfig(cfg *Config, app ApplicationCallback, logger core.Logge
140141 return coap .DialUDP (ctx , addr , opts ... )
141142 }
142143
143- opts := []core.OptionFunc {
144- core .WithDialDTLS (dialDTLS ),
145- core .WithDialTLS (dialTLS ),
146- core .WithDialTCP (dialTCP ),
147- core .WithDialUDP (dialUDP ),
148- core .WithLogger (logger ),
144+ opts := []ClientOptionFunc {
145+ WithDialDTLS (dialDTLS ),
146+ WithDialTLS (dialTLS ),
147+ WithDialTCP (dialTCP ),
148+ WithDialUDP (dialUDP ),
149+ WithLogger (logger ),
150+ WithObserverConfig (ObserverConfig {
151+ PollingInterval : observerPollingInterval ,
152+ FailureThreshold : cfg .ObserverFailureThreshold ,
153+ }),
154+ WithCacheExpiration (cacheExpiration ),
149155 }
150156
151157 deviceOwner , err := NewDeviceOwnerFromConfig (cfg , dialTLS , dialDTLS , app )
152158 if err != nil {
153159 return nil , err
154160 }
155- return NewClient (app , deviceOwner , cacheExpiration , observerPollingInterval , opts ... )
161+ return NewClient (app , deviceOwner , opts ... )
162+ }
163+
164+ // ObserverConfig is a configuration of the devices observation.
165+ type ObserverConfig struct {
166+ // PollingInterval is a time between two consecutive observations.
167+ PollingInterval time.Duration
168+ // FailureThreshold is a number of consecutive observation failures after which the device is marked as offline.
169+ FailureThreshold uint8
170+ }
171+
172+ type ClientConfig struct {
173+ CoreOptions []core.OptionFunc
174+ // CacheExpiration is a time after which the device entry in cache is invalidated.
175+ CacheExpiration time.Duration
176+ // Observer is a configuration of the devices observation.
177+ Observer ObserverConfig
178+ }
179+
180+ type ClientOptionFunc func (ClientConfig ) ClientConfig
181+
182+ // WithObserverConfig sets the observer config.
183+ func WithObserverConfig (observerConfig ObserverConfig ) ClientOptionFunc {
184+ return func (cfg ClientConfig ) ClientConfig {
185+ if observerConfig .PollingInterval <= 0 {
186+ observerConfig .PollingInterval = 3 * time .Second
187+ }
188+ if observerConfig .FailureThreshold <= 0 {
189+ observerConfig .FailureThreshold = 3
190+ }
191+ cfg .Observer = observerConfig
192+ return cfg
193+ }
194+ }
195+
196+ func WithCacheExpiration (cacheExpiration time.Duration ) ClientOptionFunc {
197+ return func (cfg ClientConfig ) ClientConfig {
198+ cfg .CacheExpiration = cacheExpiration
199+ return cfg
200+ }
201+ }
202+
203+ func WithTLS (tlsConfig * core.TLSConfig ) ClientOptionFunc {
204+ return func (cfg ClientConfig ) ClientConfig {
205+ if tlsConfig != nil {
206+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithTLS (tlsConfig ))
207+ }
208+ return cfg
209+ }
210+ }
211+
212+ func WithLogger (logger core.Logger ) ClientOptionFunc {
213+ return func (cfg ClientConfig ) ClientConfig {
214+ if logger != nil {
215+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithLogger (logger ))
216+ }
217+ return cfg
218+ }
219+ }
220+
221+ func WithDialDTLS (dial core.DialDTLS ) ClientOptionFunc {
222+ return func (cfg ClientConfig ) ClientConfig {
223+ if dial != nil {
224+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithDialDTLS (dial ))
225+ }
226+ return cfg
227+ }
228+ }
229+
230+ func WithDialTLS (dial core.DialTLS ) ClientOptionFunc {
231+ return func (cfg ClientConfig ) ClientConfig {
232+ if dial != nil {
233+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithDialTLS (dial ))
234+ }
235+ return cfg
236+ }
237+ }
238+
239+ func WithDialTCP (dial core.DialTCP ) ClientOptionFunc {
240+ return func (cfg ClientConfig ) ClientConfig {
241+ if dial != nil {
242+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithDialTCP (dial ))
243+ }
244+ return cfg
245+ }
246+ }
247+
248+ func WithDialUDP (dial core.DialUDP ) ClientOptionFunc {
249+ return func (cfg ClientConfig ) ClientConfig {
250+ if dial != nil {
251+ cfg .CoreOptions = append (cfg .CoreOptions , core .WithDialUDP (dial ))
252+ }
253+ return cfg
254+ }
156255}
157256
158257// NewClient constructs a new local client.
159258func NewClient (
160259 app ApplicationCallback ,
161260 deviceOwner DeviceOwner ,
162- cacheExpiration time.Duration ,
163- observerPollingInterval time.Duration ,
164- opt ... core.OptionFunc ,
261+ opt ... ClientOptionFunc ,
165262) (* Client , error ) {
166263 if app == nil {
167264 return nil , fmt .Errorf ("missing application callback" )
168265 }
169266 if deviceOwner == nil {
170267 return nil , fmt .Errorf ("missing device owner callback" )
171268 }
172- var coreCfg core.Config
269+ clientCfg := ClientConfig {
270+ CacheExpiration : time .Hour ,
271+ Observer : ObserverConfig {
272+ PollingInterval : time .Second * 3 ,
273+ FailureThreshold : 3 ,
274+ },
275+ }
173276 for _ , o := range opt {
277+ clientCfg = o (clientCfg )
278+ }
279+
280+ var coreCfg core.Config
281+ for _ , o := range clientCfg .CoreOptions {
174282 coreCfg = o (coreCfg )
175283 }
176284
@@ -181,27 +289,27 @@ func NewClient(
181289 GetCertificate : deviceOwner .GetIdentityCertificate ,
182290 GetCertificateAuthorities : deviceOwner .GetIdentityCACerts ,
183291 }
184- opt = append (
292+ clientCfg . CoreOptions = append (
185293 []core.OptionFunc {
186294 core .WithTLS (& tls ),
187295 core .WithLogger (coreCfg .Logger ),
188296 },
189- opt ... ,
297+ clientCfg . CoreOptions ... ,
190298 )
191- oc := core .NewClient (opt ... )
299+ oc := core .NewClient (clientCfg . CoreOptions ... )
192300 pollInterval := time .Second * 10
193- if cacheExpiration / 2 > pollInterval {
194- pollInterval = cacheExpiration / 2
301+ if clientCfg . CacheExpiration / 2 > pollInterval {
302+ pollInterval = clientCfg . CacheExpiration / 2
195303 }
196304 client := Client {
197- client : oc ,
198- app : app ,
199- deviceCache : NewDeviceCache (cacheExpiration , pollInterval , coreCfg .Logger ),
200- observeResourceCache : coapSync .NewMap [string , * observationsHandler ](),
201- deviceOwner : deviceOwner ,
202- subscriptions : make (map [string ]subscription ),
203- observerPollingInterval : observerPollingInterval ,
204- logger : coreCfg .Logger ,
305+ client : oc ,
306+ app : app ,
307+ deviceCache : NewDeviceCache (clientCfg . CacheExpiration , pollInterval , coreCfg .Logger ),
308+ observeResourceCache : coapSync .NewMap [string , * observationsHandler ](),
309+ deviceOwner : deviceOwner ,
310+ subscriptions : make (map [string ]subscription ),
311+ observerConfig : clientCfg . Observer ,
312+ logger : coreCfg .Logger ,
205313 }
206314 return & client , nil
207315}
@@ -223,8 +331,8 @@ type Client struct {
223331
224332 deviceCache * DeviceCache
225333
226- observeResourceCache * coapSync.Map [string , * observationsHandler ]
227- observerPollingInterval time. Duration
334+ observeResourceCache * coapSync.Map [string , * observationsHandler ]
335+ observerConfig ObserverConfig
228336
229337 deviceOwner DeviceOwner
230338
0 commit comments