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
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 87 88 89 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 54 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.
48 49 50 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 48 def stomp @stomp end |
Instance Method Details
#eibd_connection(conn_symbol, conn_ok_symbol) ⇒ Object
get handle to eibd monitor connection
111 112 113 114 115 116 117 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 111 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
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 92 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
120 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 120 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
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 204 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
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 175 176 177 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 126 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)
184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 184 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
123 |
# File 'lib/ansible/knx/knx_transceiver.rb', line 123 def send_conn; return(eibd_connection(:@send_conn, :@send_conn_ok)); end |