def process_datagram(cli, msg): src_id = int(msg[7:10], 16) s = cli.sock #for now we assume a one frame datagram dest_node_alias = int(msg[4:7], 16) dest_node, cli_dest = buses.find_managed_node(dest_node_alias) if dest_node is None or not dest_node.permitted: #not for us or the node is not ready yet debug("Frame is not for us or node is not ready!!") #forward to all other OLCB clients OLCB_serv.transfer(msg.encode('utf-8'), cli) return src_node = find_node(src_id) if dest_node.current_write is not None: #if there is a write in progress then this datagram is part of it if memory_write(s, dest_node, src_node, msg): cli_dest.bus.nodes_db.synced = False elif msg[11:15] == "2043": #read command for CDI address = int(msg[15:23], 16) debug("read command, address=", int(msg[15:23], 16)) s.send((":X19A28" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + ";").encode('utf-8')) debug("datagram received ok sent --->", (":X19A28" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + ";").encode("utf-8")) send_CDI(s, dest_node, src_node, address, int(msg[23:25], 16)) elif msg[11:14] == "200" or msg[11:14] == "204": #read/write command s.send((":X19A28" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + ";").encode('utf-8')) debug("datagram received ok sent --->", (":X19A28" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + ";").encode("utf-8")) if msg[13] == "4": address = int(msg[15:23], 16) memory_read(s, dest_node, src_node, address, msg) elif msg[13] == "0": if memory_write(s, dest_node, src_node, msg): cli_dest.bus.nodes_db.synced = False elif msg[11:13] == "20": #other commands than read/write if msg[13:15] == "A8": #CDI update complete, we do not have to reply so we dont for now debug("Update complete received from node ", src_node.ID) elif msg[13:15] == "80": #Get configurations options dgram = Datagram_content.build_get_config_opt_reply( dest_node, src_node) s.send(dgram.to_gridconnect()) debug("---> S: config opt reply=", dgram.to_gridconnect())
def check_alias(alias): """ Checks if the alias is used by one of our nodes if yes transition the node to inhibited state, send AMR frame and reset alias negotiation for the node """ node, node_cli = buses.find_managed_node(alias) if node_cli is None: return None node.permitted = False #reset the alias negotiation alias_neg = node.create_alias_negotiation() #loop while we find an unused alias while (alias_neg.aliasID in reserved_aliases) or (get_alias_neg_from_alias( alias_neg.aliasID) is not None): alias_neg = node.create_alias_negotiation() #register to the bus alias neg list node_cli[1].bus.nodes_in_alias_negotiation.append((node, alias_neg)) #also add it to the list of aliases negotiation list_alias_neg.append(alias_neg) #send AMR to all openlcb nodes OLCB_serv.send(Frame.build_AMR(node))
def global_frame(cli, msg): first_b = int(msg[2:4], 16) var_field = int(msg[4:7], 16) src_id = int(msg[7:10], 16) s = cli.sock if var_field == 0x490: #forward to all other clients OLCB_serv.transfer(msg.encode('utf-8'), cli) for b in buses.Bus_manager.buses: for c in b.clients: for n in c.managed_nodes: if n.permitted: OLCB_serv.transfer( (":X19170" + hexp(n.aliasID, 3) + "N" + hexp(n.ID, 12) + ";").encode('utf-8')) debug("Sent---> :X19170" + hexp(n.aliasID, 3) + "N" + hexp(n.ID, 12) + ";") elif var_field == 0x828: #Protocol Support Inquiry dest_node_alias = int(msg[12:15], 16) dest_node, cli_dest = buses.find_managed_node(dest_node_alias) if dest_node is not None: #FIXME: set correct bits s.send((":X19668" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + hexp(SPSP | SNIP | CDIP, 6) + "000000;").encode("utf-8")) debug("sent--->:X19668" + hexp(dest_node.aliasID, 3) + "N0" + hexp(src_id, 3) + hexp(SPSP | SNIP | CDIP, 6) + "000000;") elif var_field == 0xDE8: #Simple Node Information Request dest_node_alias = int(msg[12:15], 16) dest_node, cli_dest = buses.find_managed_node(dest_node_alias) if dest_node is not None: debug("sent SNIR Reply") #s.send((":X19A08"+hexp(gw_add.aliasID,3)+"N1"+hexp(src_id,3)+"04;").encode("utf-8"))#SNIR header #print(":X19A08"+hexp(gw_add.aliasID,3)+"N1"+hexp(src_id,3)+"04;") #FIXME: src_node = find_node(src_id) send_fields(s, dest_node, 0xA08, mfg_name_hw_sw_version, src_node) elif var_field == 0x5B4: #PCER (event) #transfer to all other openlcb clients OLCB_serv.transfer(msg.encode('utf-8'), cli) ev_id = bytes([int(msg[11 + i * 2:13 + i * 2], 16) for i in range(8)]) debug("received event:", ev_id) for b in buses.Bus_manager.buses: path = b.path_to_nodes_files if path is not None: if path != "": path += "/" path += str(n.ID) + ".outputs" for c in b.clients: for n in c.managed_nodes: if n.permitted: n.consume_event(Event(ev_id), path) elif var_field == 0x914 or var_field == 0x8F4: #identify producer/consumer #transfer to all other openlcb clients OLCB_serv.transfer(msg.encode('utf-8'), cli) process_id_prod_consumer(cli, msg) elif var_field == 0x970 or var_field == 0x968: #identify events #transfer to all other openlcb clients OLCB_serv.transfer(msg.encode('utf-8'), cli) identify_events(msg, cli) elif var_field == 0x4C4 or var_field == 0x4C5 or var_field == 0x4C7: #consumer identified OLCB_serv.transfer(msg.encode('utf-8'), cli) consum_identified(msg, cli) elif var_field == 0x544 or var_field == 0x545 or var_field == 0x547: #producer identified OLCB_serv.transfer(msg.encode('utf-8'), cli) produc_identified(msg, cli)
def can_control_frame(cli, msg): #transfer to all other openlcb clients OLCB_serv.transfer(msg.encode('utf-8'), cli) first_b = int(msg[2:4], 16) var_field = int(msg[4:7], 16) src_id = int(msg[7:10], 16) data_needed = False if first_b & 0x7 >= 4 and first_b & 0x7 <= 7: debug("CID Frame n°", first_b & 0x7, " * ", hex(var_field)) #full_ID = var_field << 12*((first_b&0x7) -4) new = False if first_b & 0x7 == 7: if get_alias_neg_from_alias(src_id) is not None: debug("Alias collision") #fixme: what to do here?? return alias_neg = Alias_negotiation(src_id) new = True else: alias_neg = get_alias_neg_from_alias(src_id) if alias_neg is None: debug("CID frame with no previous alias negotiation!") alias_neg = Alias_negotiation(src_id, 0, 8 - (first_b & 0x07)) new = True alias_neg.next_step(var_field) if new: list_alias_neg.append(alias_neg) #if we have a node in permitted state we send an AMD frame node_cli = buses.find_managed_node(src_id) if node_cli is not None: OLCB_serv.send(Frame.build_AMD(node_cli[0])) elif first_b & 0x7 == 0: if var_field == 0x700: debug("RID Frame * full ID=") neg = get_alias_neg_from_alias(src_id) if neg is None: #no CID before that create the alias_negotiation neg = Alias_negotiation(src_id, 0, 4) list_alias_neg.append(neg) reserve_aliasID(src_id) #create node but not in permitted state new_node(Node(neg.fullID, False, neg.aliasID)) check_alias(src_id) elif var_field == 0x701: debug("AMD Frame") check_alias(src_id) if src_id in reserved_aliases: node = find_node(src_id) if node is None: debug("AMD frame received (alias=", src_id, ") but node does not exist!") else: #change to permitted state node.permitted = True else: debug("AMD frame received (alias=", src_id, ") but not reserved before!") #create alias, reserve it neg = Alias_negotiation(src_id, 0, 4) list_alias_neg.append(neg) reserve_aliasID(src_id) #create node in permitted state new_node(Node(int(msg[11:23], 16), True, src_id)) data_needed = True #we could check the fullID elif var_field == 0x702: debug("AME Frame") for b in buses.Bus_manager.buses: for c in b.clients: for n in c.managed_nodes: if n.permitted: f = Frame.build_AMD(n) OLCB_serv.send(f) debug("sent---->:", f.to_gridconnect()) debug("Sent---> :X19170" + hexp(n.aliasID, 3) + "N" + hexp(n.ID, 12) + ";") elif var_field == 0x703: #FIXME! debug("AMR Frame") data_nedded = True elif var_field >= 0x710 and var_field <= 0x713: debug("Unknown Frame") debug(hexp(src_id, 3)) if data_needed and not data_present: debug("Data needed but none is present!") return