Skip to content

Commit

Permalink
fix(knx\tunnel_client): retry remaining check
Browse files Browse the repository at this point in the history
and track if connecting
  • Loading branch information
stakach committed Jul 22, 2024
1 parent 7b51c99 commit f96f55e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: knx
version: 1.2.1
version: 1.2.2
crystal: ">= 0.36.1"

dependencies:
Expand Down
51 changes: 34 additions & 17 deletions src/knx/tunnel_client.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class KNX

getter control : Socket::IPAddress
getter? connected : Bool = false
getter? connecting : Bool = false
getter channel_id : UInt8 = 0_u8
getter sequence : UInt8 = 0_u8
property timeout : Time::Span
Expand All @@ -22,7 +23,7 @@ class KNX
alias Request = ConnectRequest | ConnectStateRequest | DisconnectRequest | TunnelRequest

@request_queue : Array(Request) = [] of Request
@channel : Channel(Nil) = Channel(Nil).new
@channel : Channel(Nil) = Channel(Nil).new(1)
@retries : Int32 = 0
@mutex : Mutex = Mutex.new

Expand Down Expand Up @@ -55,7 +56,7 @@ class KNX
@retries = 0
@waiting = false
pending = @mutex.synchronize do
@request_queue.shift
@request_queue.shift?
@request_queue.first?
end
perform_send(pending) if pending
Expand All @@ -68,14 +69,14 @@ class KNX
@retries += 1

if pending = @mutex.synchronize { @request_queue.first? }
if @retries <= @max_retries
if @retries > @max_retries
perform_send pending
else
@waiting = false
@connected = false
@mutex.synchronize { @request_queue.clear }
@on_transmit.try &.call(KNX::DisconnectRequest.new(@channel_id, @control).to_slice) rescue nil
@on_state_change.try &.call(false, KNX::ConnectionError::SubnetworkIssue) rescue nil
if connected?
@on_transmit.try &.call(KNX::DisconnectRequest.new(@channel_id, @control).to_slice) rescue nil
end
perform_state_change(false, KNX::ConnectionError::SubnetworkIssue) rescue nil
end
end
end
Expand All @@ -88,8 +89,11 @@ class KNX

# establish comms
def connect : Nil
return if connected?
raise "client has been shutdown" if @channel.closed?
@mutex.synchronize do
return if connecting? || connected?
@connecting = true
end
send KNX::ConnectRequest.new(@control)
end

Expand All @@ -107,11 +111,13 @@ class KNX

# perform a hard and fast disconnect, instance is not re-usable
def shutdown! : Nil
return unless connected?
@mutex.synchronize { @request_queue.clear }
@channel.close
@connected = false
@on_transmit.try &.call(KNX::DisconnectRequest.new(@channel_id, @control).to_slice) rescue nil

if connected?
@connected = false
@on_transmit.try &.call(KNX::DisconnectRequest.new(@channel_id, @control).to_slice) rescue nil
end
end

def action(address : String, data, **options)
Expand All @@ -130,6 +136,19 @@ class KNX
send KNX::TunnelRequest.new(@channel_id, message)
end

protected def perform_state_change(connected : Bool, error : KNX::ConnectionError)
@mutex.synchronize do
@connected = connected
@connecting = false
if !connected
@request_queue.clear
@channel.send(nil) if @waiting
end
end

@on_state_change.try &.call(connected, error)
end

# connected or disconnected state changed
def on_state_change(&@on_state_change : Bool, KNX::ConnectionError ->)
end
Expand Down Expand Up @@ -178,10 +197,9 @@ class KNX

connected = packet.status.no_error?
@channel_id = packet.channel_id
@connected = connected
@sequence = 0_u8
@channel.send(nil) if @waiting
@on_state_change.try &.call(connected, packet.status)
perform_state_change(connected, packet.status)
packet
end

Expand All @@ -204,15 +222,15 @@ class KNX
@channel.send(nil) if @waiting
connected = packet.status.no_error?
if connected != @connected
@connected = connected
@on_state_change.try &.call(connected, packet.status)
perform_state_change(connected, packet.status)
end
packet
end

def process(packet : KNX::DisconnectRequest)
if packet.channel_id == @channel_id
@on_transmit.try &.call(KNX::DisconnectResponse.new(@channel_id).to_slice) rescue nil
perform_state_change(false, packet.status)
end
packet
end
Expand All @@ -222,8 +240,7 @@ class KNX

@channel.send(nil) if @waiting
if packet.status.no_error? || packet.status.connection_id? || packet.status.sequence_number?
@connected = false
@on_state_change.try &.call(false, packet.status)
perform_state_change(false, packet.status)
end
packet
end
Expand Down

0 comments on commit f96f55e

Please sign in to comment.