@@ -22,6 +22,7 @@ public actor SMADevice
22
22
struct QueryObject : Hashable
23
23
{
24
24
let objectid : String
25
+ let path : String
25
26
let interval : Int
26
27
}
27
28
@@ -38,6 +39,8 @@ public actor SMADevice
38
39
39
40
var objectsToQueryContinously = [ String: QueryObject] ( )
40
41
var objectsToQueryNext = [ QueryElement] ( )
42
+ var lastRequestSentDate = Date . distantPast
43
+ let minimumRequestInterval = 1.0 / 20.0 // 1 / maximumRequestsPerSecond
41
44
42
45
let requestAllObjects : Bool
43
46
@@ -47,6 +50,7 @@ public actor SMADevice
47
50
let httpClient : HTTPClient
48
51
private var sessionid : String ?
49
52
53
+ let udpReceiver : UDPReceiver
50
54
let udpEmitter : UDPEmitter ?
51
55
var udpSystemId : UInt16 = 0xFFFF
52
56
var udpSerial : UInt32 = 0xFFFF_FFFF
@@ -60,7 +64,7 @@ public actor SMADevice
60
64
private var refreshTask : Task < Void , Error > ?
61
65
private var tagTranslator = SMATagTranslator . shared
62
66
63
- public init ( address: String , userright: UserRight = . user, password: String = " 00000 " , publisher: SMAPublisher ? = nil , refreshInterval: Int = 30 , interestingPaths: [ String : Int ] = [ : ] , requestAllObjects: Bool = false , udpEmitter: UDPEmitter ? = nil ) async throws
67
+ public init ( address: String , userright: UserRight = . user, password: String = " 00000 " , publisher: SMAPublisher ? = nil , refreshInterval: Int = 30 , interestingPaths: [ String : Int ] = [ : ] , requestAllObjects: Bool = false , bindAddress : String = " 0.0.0.0 " , udpEmitter: UDPEmitter ? = nil ) async throws
64
68
{
65
69
self . address = address
66
70
self . userright = userright
@@ -72,6 +76,10 @@ public actor SMADevice
72
76
self . interestingPaths = interestingPaths
73
77
self . requestAllObjects = requestAllObjects
74
78
self . udpEmitter = udpEmitter
79
+
80
+ self . udpReceiver = try UDPReceiver ( bindAddress: bindAddress, listenPort: 0 )
81
+
82
+
75
83
name = address
76
84
hasDeviceName = false
77
85
@@ -114,7 +122,7 @@ public extension SMADevice
114
122
return nil
115
123
}
116
124
117
- JLog . trace ( " received udp packet: \( data. hexDump) " )
125
+ JLog . debug ( " \( address ) : received udp packet:\( data. hexDump) " )
118
126
119
127
let smaPacket : SMAPacket
120
128
@@ -199,7 +207,7 @@ public extension SMADevice
199
207
{
200
208
if obisvalue. mqtt != . invisible
201
209
{
202
- try ? await publisher? . publish ( to: name + " / " + obisvalue. topic, payload: obisvalue. json, qos: . atLeastOnce , retain: obisvalue. mqtt == . retained)
210
+ try ? await publisher? . publish ( to: name + " / " + obisvalue. topic, payload: obisvalue. json, qos: . atMostOnce , retain: obisvalue. mqtt == . retained)
203
211
}
204
212
}
205
213
@@ -236,12 +244,16 @@ public extension SMADevice
236
244
{
237
245
let objectToQuery = try getNextRequest ( )
238
246
239
- let timeToWait = objectToQuery. nextReadDate. timeIntervalSinceNow
247
+ let nextReadDate = max ( objectToQuery. nextReadDate , lastRequestSentDate + minimumRequestInterval )
248
+
249
+ let timeToWait = nextReadDate. timeIntervalSinceNow
240
250
241
251
if timeToWait > 0
242
252
{
243
253
try await Task . sleep ( for: . seconds( timeToWait) )
244
254
}
255
+ lastRequestSentDate = Date ( )
256
+
245
257
try await udpQueryObject ( objectID: objectToQuery. objectid)
246
258
}
247
259
@@ -267,7 +279,9 @@ public extension SMADevice
267
279
}
268
280
269
281
JLog . trace ( " \( address) : sending udp packet: \( packetToSend) " )
270
- await udpEmitter? . sendPacket ( data: [ UInt8] ( packetToSend. hexStringToData ( ) ) , address: address, port: 9522 )
282
+ let packet = try await udpReceiver. sendReceivePacket ( data: [ UInt8] ( packetToSend. hexStringToData ( ) ) , address: address, port: 9522 , receiveTimeout: 1.0 )
283
+
284
+ let _ = await receivedUDPData ( packet. data)
271
285
}
272
286
}
273
287
@@ -335,12 +349,13 @@ extension SMADevice
335
349
name = deviceName
336
350
}
337
351
352
+ try await getInformationDictionary ( atPath: " /dyn/getDashValues.json " )
353
+ try await getInformationDictionary ( atPath: " /dyn/getAllOnlValues.json " )
354
+
338
355
for objectid in tagTranslator. smaObjectDefinitions. keys
339
356
{
340
357
addObjectToQueryContinouslyIfNeeded ( objectid: objectid)
341
358
}
342
- // try await getInformationDictionary(atPath: "/dyn/getDashValues.json")
343
- // try await getInformationDictionary(atPath: "/dyn/getAllOnlValues.json")
344
359
345
360
try ? await logout ( )
346
361
}
@@ -436,21 +451,34 @@ extension SMADevice
436
451
return nil
437
452
}
438
453
439
- func objectIdIsInteresting( _ objectid: String ) -> Int ?
454
+ func objectIdIsInteresting( _ objectid: String ) -> ( path : String , interval : Int ? )
440
455
{
441
456
let path = " / " + ( tagTranslator. objectsAndPaths [ objectid] ? . path ?? " unkown-id- \( objectid) " )
442
457
443
- return pathIsInteresting ( path)
458
+ let interval = pathIsInteresting ( path)
459
+
460
+ JLog . debug ( " \( address) : \( objectid) \( path) interval: \( interval ?? - 1 ) " )
461
+
462
+ return ( path: path, interval: interval)
444
463
}
445
464
446
465
@discardableResult
447
466
func addObjectToQueryContinouslyIfNeeded( objectid: String ) -> Bool
448
467
{
449
468
JLog . trace ( " \( address) :working on objectId: \( objectid) " )
450
469
451
- if let interval = objectIdIsInteresting ( objectid)
470
+ let ( path, interval) = objectIdIsInteresting ( objectid)
471
+
472
+ if let interval
452
473
{
453
- let queryObject = objectsToQueryContinously [ objectid] ?? QueryObject ( objectid: objectid, interval: interval)
474
+ if let inuse = objectsToQueryContinously. values. first ( where: { $0. path == path } )
475
+ {
476
+ JLog . notice ( " \( address) : Won't query objectid: \( objectid) - object with same path: \( inuse. objectid) path: \( inuse. path) " )
477
+ return false
478
+ }
479
+ JLog . debug ( " \( address) : adding to objectsToQueryContinously objectid: \( objectid) path: \( path) interval: \( interval) " )
480
+
481
+ let queryObject = objectsToQueryContinously [ objectid] ?? QueryObject ( objectid: objectid, path: path, interval: interval)
454
482
455
483
if interval <= queryObject. interval
456
484
{
@@ -498,7 +526,7 @@ extension SMADevice
498
526
if hasDeviceName,
499
527
addObjectToQueryContinouslyIfNeeded ( objectid: objectId. key)
500
528
{
501
- try await publisher? . publish ( to: mqttPath, payload: singleValue. json, qos: . atMostOnce, retain: true )
529
+ try await publisher? . publish ( to: mqttPath, payload: singleValue. json, qos: . atMostOnce, retain: false )
502
530
}
503
531
}
504
532
catch
0 commit comments