Class: Ansible::KNX::KNX_Transceiver
- Inherits:
-
Transceiver
- Object
- Transceiver
- Ansible::KNX::KNX_Transceiver
- Includes:
- AnsibleCallback
- Defined in:
- lib/ansible/knx/knx_transceiver.rb
Overview
The KNX Transceiver is an object responsible for i/o with the KNX bus. It does so using eibd, part of BCU-SDK the open-source libary for KNX.
Defined Under Namespace
Classes: NormalExit
Instance Attribute Summary collapse
-
#stomp ⇒ Object
readonly
Returns the value of attribute stomp.
Attributes inherited from Transceiver
Instance Method Summary collapse
-
#eibd_connection(conn_symbol, conn_ok_symbol) ⇒ Object
get handle to eibd monitor connection.
-
#init_eibd(conn_symbol, conn_ok_symbol) ⇒ Object
initialize eibd connection.
-
#initialize(connURL = KNX_URL) ⇒ KNX_Transceiver
constructor
initialize a KNXTranceiver.
-
#monitor_conn ⇒ Object
get handle to KNX monitoring connection, reconnecting if necessary.
-
#read_eibd_cache(ga, cache_only = false) ⇒ Object
(Try to) read a groupaddr from eibd cache.
-
#run ⇒ Object
the main KNX transceiver thread.
-
#send_apdu_raw(dest, apdu) ⇒ Object
send a raw APDU to the KNX bus.
-
#send_conn ⇒ Object
get handle to KNX sending connection, reconnecting if necessary.
Methods included from AnsibleCallback
#add_callback, #fire_callback, #remove_callback
Methods inherited from Transceiver
Constructor Details
#initialize(connURL = KNX_URL) ⇒ KNX_Transceiver
initialize a KNXTranceiver
*params:
[connURL] an eibd connection URL. see eibd --help for acceptable values
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 51 def initialize(connURL=KNX_URL) raise "Already initialized!" unless Ansible::KNX::KNXValue.transceiver.nil? @connURL = connURL @monitor_conn_ok, @send_conn_ok = false, false @send_mutex = Mutex.new() @knxbuf = EIBBuffer.new() # super() # store reference to ourselves to the classes that use us Ansible::KNX::KNXValue.transceiver = self # register default handler for KNX frames add_callback(:onKNXtelegram) { | sender, cb, frame | puts(frame_inspect(frame)) if $DEBUG case frame.apci.value when 0 then # A_GroupValue_Read puts "read request for knx address #{addr2str(frame.dst_addr, frame.daf)}" AnsibleValue[:groups => [frame.dst_addr]].each { |v| unless v.current_value.nil? then puts "==> responding with value #{v}" send_apdu_raw(frame.dst_addr, v.to_apdu(0x40)) end } when 1 then # A_GroupValue_Response puts "response frame by #{addr2str(frame.src_addr)} for knx address #{addr2str(frame.dst_addr, frame.daf)}" AnsibleValue[:groups => [frame.dst_addr]].each { |v| v.update_from_frame(frame) puts "synchronized knx value #{v} from frame #{frame.inspect}" if $DEBUG } when 2 then # A_GroupValue_Write AnsibleValue[:groups => [frame.dst_addr]].each { |v| v.update_from_frame(frame) puts "updated knx value #{v} from frame #{frame.inspect}" if $DEBUG } end } end |
Instance Attribute Details
#stomp ⇒ Object (readonly)
Returns the value of attribute stomp.
45 46 47 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 45 def stomp @stomp end |
Instance Method Details
#eibd_connection(conn_symbol, conn_ok_symbol) ⇒ Object
get handle to eibd monitor connection
108 109 110 111 112 113 114 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 108 def eibd_connection(conn_symbol, conn_ok_symbol) if instance_variable_get(conn_ok_symbol) then return(instance_variable_get(conn_symbol)) else init_eibd(conn_symbol, conn_ok_symbol) end end |
#init_eibd(conn_symbol, conn_ok_symbol) ⇒ Object
initialize eibd connection
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 89 def init_eibd(conn_symbol, conn_ok_symbol) unless instance_variable_get(conn_ok_symbol) begin puts("KNX: init #{conn_symbol} to #{@connURL}") conn = EIBConnection.new() conn.EIBSocketURL(@connURL) instance_variable_set(conn_symbol, conn) instance_variable_set(conn_ok_symbol, true) return(conn) rescue Errno::ECONNRESET => e conn.EIBClose instance_variable_set(conn_ok_symbol, false) puts "init_eibd: Disconnected, retrying in 10 seconds..." sleep(10) end end end |
#monitor_conn ⇒ Object
get handle to KNX monitoring connection, reconnecting if necessary
117 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 117 def monitor_conn; return(eibd_connection(:@monitor_conn, :@monitor_conn_ok)); end |
#read_eibd_cache(ga, cache_only = false) ⇒ Object
(Try to) read a groupaddr from eibd cache.
return it if found, otherwise query the bus. In the latter case, the main receiver thread (in run()) will act on the response.
-
Arguments:
- ga
-
Fixnum: group address (0-65535)
- cache_only
-
boolean: when true, do not query the bus
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 201 def read_eibd_cache(ga, cache_only=false) src = EIBAddr.new() buf = EIBBuffer.new() result = nil @send_mutex.synchronize { # query eibd for a cached value if (send_conn.EIB_Cache_Read_Sync(ga, src, buf, 0) == -1) then # value not found in cache puts "groupaddress #{addr2str(ga, true)} not found in cache." unless cache_only then puts ".. requesting value on bus .." if (send_conn.EIBOpenT_Group(ga, 1) == -1) then raise("KNX client: error setting socket mode") end # send a read request to the bus send_conn.EIBSendAPDU([0,0x00]) end send_conn.EIBReset() else send_conn.EIBReset() # value found in cache.. puts "found in cache, last sender was #{addr2str(src.data)}" result = buf.buffer end } return result end |
#run ⇒ Object
the main KNX transceiver thread
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 123 def run() puts("KNX Transceiver thread is running!") @stomp = nil begin #### part 1: connect to STOMP broker @stomp = OnStomp.connect(STOMP_URL) #### part 2: subscribe to command channel, listen for messages and pass them to KNX # @stomp.subscribe KNX_COMMAND_TOPIC do |msg| # dest = msg.headers['dest_addr'].to_i # #TODO: check address limits # apdu = Marshal.load(CGI.unescape(msg.body)) # send_apdu_raw(dest, apdu) # end ##### part 3: monitor KNX bus, post all activity to /knx/monitor vbm = monitor_conn.EIBOpenVBusmonitor() loop do len = monitor_conn.EIBGetBusmonitorPacket(@knxbuf) #puts "knxbuffer=="[email protected] frame = L_DATA_Frame.read(@knxbuf.buffer.pack('c*')) #puts "frame:\n\t" headers = {} frame.field_names.each { |fieldname| field = frame.send(fieldname) #puts "\t#{fieldname} == #{field.value}" headers[fieldname] = CGI.escape(field.value.to_s) } @stomp.send(KNX_MONITOR_TOPIC, "KNX Activity", headers) #puts Ansible::KNX::APCICODES[frame.apci] + " packet from " + # addr2str(frame.src_addr) + " to " + addr2str(frame.dst_addr, frame.daf) + # " priority=" + Ansible::KNX::PRIOCLASSES[frame.prio_class] fire_callback(:onKNXtelegram, frame.dst_addr, frame) # end rescue Errno::ECONNRESET => e @monitor_conn_ok = false puts("EIBD disconnected! retrying in 10 seconds..") sleep(10) retry rescue NormalExit => e puts("KNX transceiver terminating gracefully...") rescue Exception => e puts("Exception in KNX server thread: #{e}") puts("backtrace:\n " << e.backtrace.join("\n ")) sleep(3) retry # ensure #puts "Closing EIB connection..." #@monitor_conn.EIBClose() if @monitor_conn #puts "Closing STOMP connection..." #@stomp.disconnect if @stomp end end |
#send_apdu_raw(dest, apdu) ⇒ Object
send a raw APDU to the KNX bus.
-
Arguments:
- dest
-
destination (16-bit integer)
- apdu
-
raw APDU (binary string)
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 181 def send_apdu_raw(dest, apdu) @send_mutex.synchronize { raise 'apdu must be a byte array!' unless apdu.is_a?Array puts("KNX transceiver: sending to group address #{dest}, #{apdu.inspect}") if $DEBUG if (send_conn.EIBOpenT_Group(dest, 1) == -1) then raise("KNX client: error setting socket mode") end send_conn.EIBSendAPDU(apdu) send_conn.EIBReset() } end |
#send_conn ⇒ Object
get handle to KNX sending connection, reconnecting if necessary
120 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 120 def send_conn; return(eibd_connection(:@send_conn, :@send_conn_ok)); end |