def _process_leader(self): print_debug(3, "Process Leader") """ if state == self.mesh.STATE_LEADER_SINGLE: # no neighbors routers, so nothing left to do return """ # cleanup old entries self.mesh.leader_dict_cleanup() if time.time() - self.leader_ts < self.LEADER_INTERVAL: return # ask each router self.leader_ts = time.time() router_list = self.mesh.routers_rloc_list(60) router_num = min(len(router_list), 5) idx = 0 for router_pair in router_list[:router_num]: (age, router) = router_pair self.send_pack(self.PACK_LEADER_ASK_NEIGH, '', router) print_debug(3, "Leader inquire Router %s" % router) idx = idx + 1 if idx < router_num: time.sleep(.5)
def border_router(self, enable, prio=0, br_mess_cb=None): """ Disables/Enables the Border Router functionality, with priority and callback """ net_list = self.mesh.mesh.border_router() print_debug(3, "State:" + str(enable) + "BR: " + str(net_list)) if not enable: # disable all BR network registrations (possible multiple) self.br_handler = None for net in net_list: self.mesh.mesh.border_router_del(net.net) print_debug(3, "Done remove BR") else: self.br_handler = br_mess_cb # check if BR already added try: # print_debug(3, net[0].net) # print_debug(3, self.BR_NET_ADDRESS) # if net[0].net != self.BR_NET_ADDRESS: if not net_list[0].net.startswith(self.BR_NET_ADDRESS[0:-3]): # enable BR self.mesh.mesh.border_router(self.BR_NET_ADDRESS, prio) print_debug(3, "Done add BR") except: # enable BR self.mesh.mesh.border_router(self.BR_NET_ADDRESS, prio) print_debug(3, "Force add BR") # print again the BR, to confirm net_list = self.mesh.mesh.border_router() print_debug(3, "BR: " + str(net_list)) pass
def periodic_cb(self, alarm): # wait lock forever if self.lock.acquire(): print_debug(2, "============ MESH THREAD >>>>>>>>>>> ") t0 = time.ticks_ms() self.mesh.process() if self.mesh.is_connected(): # self.statistics.process() self.mesh.process_messages() # if Single Leader for 3 mins should reset # if self.mesh.mesh.state == self.mesh.mesh.STATE_LEADER and self.mesh.mesh.mesh.single(): # if self.single_leader_ts == 0: # # first time Single Leader, record time # self.single_leader_ts = time.time() # print("Single Leader", self.mesh.mesh.state, self.mesh.mesh.mesh.single(), # time.time() - self.single_leader_ts) # if time.time() - self.single_leader_ts > 180: # print("Single Leader, just reset") # if self.sleep_function: # self.sleep_function(1) # else: # # print("Not Single Leader", self.mesh.mesh.state, self.mesh.mesh.mesh.single()) # self.single_leader_ts = 0 self.lock.release() print_debug( 2, ">>>>>>>>>>> DONE MESH THREAD ============ %d\n" % (time.ticks_ms() - t0)) pass
def rcv_ack(self, data): """ just received an ACK for a previously sent message """ message = Message() message.unpack_ack(data) # check if message was really in send buffer if message.mac in self.dict: self.dict[message.mac].state = Message.MESS_STATE_ACK if self.on_rcv_ack: self.on_rcv_ack(message) # check if message was about picture sending, to start actual file sending mess = self.dict[message.mac] if mess.payload == 'dog': print_debug(3, 'ACK from dog message, start picture sending') del self.dict[message.mac] self.send_message(message.mac, message.TYPE_IMAGE, 'dog.jpg', message.id, time.time()) if self.on_rcv_message: mess = Message((message.mac, message.TYPE_TEXT, 'Receiving the picture', message.id+1, time.time())) self.on_rcv_message(mess) else: print_debug(3, str(message.mac) + str(self.dict)) pass
def br_send(self, data): """ if BR is available in whole Mesh, send some data """ ret = False # first, make sure this node is not BR (BR data is sent directly) if len(self.mesh.mesh.border_router()) > 0: print_debug(3, "Node is BR, so shouldn't send data to another BR") return False # check if we have a BR network prefix in ipaddr for ip in self.mesh.ipaddr(): if ip.startswith(self.BR_NET_ADDRESS[0:-4]): print_debug(3, "found BR address: %s" % ip) if time.time() - self.ext_mesh_ts >= 0: ret = True try: ip = data['ip'] port = int(data['port']) payload = data['b'] except: print_debug(3, "Error parsing packet for Mesh-external") ret = False if ret: self.send_pack(self.PACK_BR, payload, ip, port) # self.send_pack(self.PACK_BR, self.debug_data(False), self.EXTERNAL_IP) self.ext_mesh_ts = time.time() else: print_debug(3, "BR sending too fast") ret = False if not ret: print_debug(3, "no BR (mesh-external IPv6) found") return ret
def get_connections_pack(self): connections = self.get_mesh_connections() print_debug(3, "Connections " + str(connections)) data = pack('!H', len(connections)) for record in connections: (mac1, mac2, rssi) = record data = data + pack('!HHb', mac1, mac2, rssi) return data
def set_location(latitude, longitude): dlat = str(type(latitude)) dlon = str(type(longitude)) if dlat == dlon == "<class 'float'>": Gps.lat = latitude Gps.lon = longitude is_set = True else: print_debug(3, "Error parsing ", latitude, longitude)
def write_config(pymesh_config, force_restart=False): cf = open(PymeshConfig.CONFIG_FILENAME, 'w') cf.write(json.dumps(pymesh_config)) cf.close() if force_restart: print_debug(3, "write_config force restart") time.sleep(1) machine.deepsleep(1000)
def node_info_mac_pack(self, mac): node, role = self.node_info_mac(mac) if node is None: print_debug(3, "Node is None %d" % mac) return bytes() # pack type: RouterData or Child (basically NeighborData) data = pack('!B', role) data = data + node.pack() return data
def send_message(self, mac, msg_type, payload, id, ts): """ send a new message """ already = self.dict.get(mac, None) if already: print_debug(3, 'old message deleted for %X' % mac) message = Message((mac, msg_type, payload, id, ts)) self.dict[mac] = message print_debug(3, "Added new message for %X: %s" % (mac, str(payload))) return True
def send_message(self, message, answer=None): """ actual sending of a message on socket """ payload = message.pack(self.MAC, answer) pack_type = self.PACK_MESSAGE # if message.type == message.TYPE_IMAGE: # pack_type = self.PACK_FILE_SEND if payload: print_debug(4, "Send message " + str(payload)) self.send_pack(pack_type, payload, message.ip) pass
def file_transfer_done(self, rcv_data): message = Message(rcv_data) message.payload = 'Picture was received' print_debug(3, 'Picture done receiving from %d', message.mac) message.id = message.id + 1 if self.on_rcv_message: self.on_rcv_message(message) self.send_message(message.mac, message.TYPE_TEXT, 'Picture was received', message.id+1, time.time()) pass
def __init__(self, config): """ Constructor """ self.config = config config_lora = config.get('LoRa') self.lora = LoRa(mode=LoRa.LORA, region=config_lora.get("region"), frequency=config_lora.get("freq"), bandwidth=config_lora.get("bandwidth"), sf=config_lora.get("sf")) self.mesh = self.lora.Mesh() #start Mesh # get Lora MAC address #self.MAC = str(ubinascii.hexlify(lora.mac()))[2:-1] self.MAC = int(str(ubinascii.hexlify(self.lora.mac()))[2:-1], 16) #last 2 letters from MAC, as integer self.mac_short = self.MAC & 0xFFFF #int(self.MAC[-4:], 16) print_debug( 5, "LoRa MAC: %s, short: %s" % (hex(self.MAC), self.mac_short)) self.rloc16 = 0 self.rloc = '' self.net_addr = '' self.ip_eid = '' self.ip_link = '' self.state = STATE_DISABLED # a dictionary with all direct neighbors # key is MAC for each neighbor # value is pair (age, mac, rloc16, role, rssi) #self.neigh_dict = {} self.router_data = RouterData() self.router_data.mac = self.MAC # a dictionary with all routers direct neighbors # key is MAC for each router # value is pair (age, rloc, neigh_num, (age, mac, rloc16, role, rssi)) #self.leader_dict = {} self.leader_data = LeaderData() self.leader_data.mac = self.MAC # set of all MACS from whole current Mesh Network self.macs = set() self.macs_ts = -65535 # very old # list of all pairs (direct radio connections) inside Mesh self.connections = list() self.connections_ts = -65535 # very old # set a new unicast address self.unique_ip_prefix = "fdde:ad00:beef:0::" command = "ipaddr add " + self.ip_mac_unique(self.mac_short) self.mesh.cli(command)
def mesage_was_ack(self, mac, id): """ return True/False if a message was ACK """ done = False try: message = self.dict[mac] if id == message.id: if message.state == Message.MESS_STATE_ACK: done = True except: pass print_debug(3, "ACK? mac %x, id %d => %d" % (mac, id, done)) return done
def get_type(self, data): (pack_type, len1) = unpack(self.PACK_HEADER_FMT, data[:calcsize(self.PACK_HEADER_FMT)]) data = data[calcsize(self.PACK_HEADER_FMT):] len2 = len(data) if len1 != len2: print_debug(3, "PACK_HEADER length not ok %d %d" % (len1, len2)) print_debug(3, str(data)) return return (pack_type, data)
def node_info_set(self, data): (role, ) = unpack('!B', data) if role is self.STATE_ROUTER: router = RouterData(data[1:]) self.leader_data.add_router(router) print_debug(3, "Added as router %s" % router.to_string()) elif role is self.STATE_CHILD: node = NeighborData(data[1:]) router = RouterData(node) self.leader_data.add_router(router) print_debug(3, "Added as Router-Neigh %s" % router.to_string()) pass
def read_config(MAC): file = PymeshConfig.CONFIG_FILENAME pymesh_config = {} error_file = True try: import json f = open(file, 'r') jfile = f.read() f.close() try: pymesh_config = json.loads(jfile.strip()) # pymesh_config['cfg_msg'] = "Pymesh configuration read from {}".format(file) error_file = False except Exception as ex: print_debug( 1, "Error reading {} file!\n Exception: {}".format(file, ex)) except Exception as ex: print_debug( 1, "Final error reading {} file!\n Exception: {}".format( file, ex)) if error_file: # config file can't be read, so it needs to be created and saved pymesh_config = {} print_debug( 3, "Can't find" + str(file) + ", or can't be parsed as json; Set default settings and reset") # don't write MAC, just to use the hardware one pymesh_config['LoRa'] = { "region": PymeshConfig.LORA_REGION, "freq": PymeshConfig.LORA_FREQ, "bandwidth": PymeshConfig.LORA_BW, "sf": PymeshConfig.LORA_SF } pymesh_config['Pymesh'] = {"key": PymeshConfig.KEY} pymesh_config['autostart'] = PymeshConfig.AUTOSTART pymesh_config['debug'] = PymeshConfig.DEBUG_LEVEL pymesh_config['ble_api'] = PymeshConfig.BLE_API pymesh_config['ble_name_prefix'] = PymeshConfig.BLE_NAME_PREFIX pymesh_config['br_ena'] = PymeshConfig.BR_ENABLE pymesh_config['br_prio'] = PymeshConfig.BR_PRIORITY PymeshConfig.check_mac(pymesh_config, MAC) print_debug(3, "Default settings:" + str(pymesh_config)) PymeshConfig.write_config(pymesh_config, True) PymeshConfig.check_mac(pymesh_config, MAC) print_debug(3, "Settings:" + str(pymesh_config)) return pymesh_config
def neighbors_update(self): """ update neigh_dict from cli:'neighbor table' """ """ >>> print(lora.cli("neighbor table")) | Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|S|D|N| Extended MAC | +------+--------+-----+----------+-----------+-+-+-+-+------------------+ | C | 0x2801 | 219 | 0 | 0 |1|1|1|1| 0000000000000005 | | R | 0x7400 | 9 | 0 | 0 |1|0|1|1| 0000000000000002 | """ x = self.mesh.neighbors() print_debug(3, "Neighbors Table: %s" % x) if x is None: # bad read, just keep previous neigbors return # clear all pre-existing neigbors self.router_data = RouterData() self.router_data.mac = self.MAC self.router_data.rloc16 = self.rloc16 self.router_data.role = self.state self.router_data.ts = time.time() self.router_data.coord = Gps.get_location() for nei_rec in x: # nei_rec = (role=3, rloc16=10240, rssi=0, age=28, mac=5) age = nei_rec.age if age > 300: continue # shouln't add neighbors too old role = nei_rec.role rloc16 = nei_rec.rloc16 # maybe we shouldn't add Leader (because this info is already available at Leader) # if rloc16 == self.leader_rloc(): # continue rssi = nei_rec.rssi mac = nei_rec.mac neighbor = NeighborData(( mac, age, rloc16, role, rssi, )) self.router_data.add_neighbor(neighbor) #print("new Neighbor: %s"%(neighbor.to_string())) #except: # pass # add own info in dict #self.neigh_dict[self.MAC] = (0, self.rloc16, self.state, 0) print_debug(3, "Neighbors: %s" % (self.router_data.to_string())) return
def add_rcv_message(self, message): """ received a new message """ message.ts = time.time() self.rcv_dict[message.mac] = message self.rcv_mess_new = message if message.payload == b'dog':#🐕': message.payload = 'Picture started receiving' print_debug(3, 'Rcv mess about dog, so we start receiving picture') # else: # print_debug(3, 'payload is not dog') if self.on_rcv_message: self.on_rcv_message(message) return True
def __init__(self, config): """ Constructor """ self.config_lora = config.get('LoRa') self._lora_init() # get Lora MAC address #self.MAC = str(ubinascii.hexlify(lora.mac()))[2:-1] self.MAC = int(str(ubinascii.hexlify(self.lora.mac()))[2:-1], 16) #last 2 letters from MAC, as integer self.mac_short = self.MAC & 0xFFFF #int(self.MAC[-4:], 16) print_debug( 5, "LoRa MAC: %s, short: %s" % (hex(self.MAC), self.mac_short)) self.rloc16 = 0 self.rloc = '' self.net_addr = '' self.ip_eid = '' self.ip_link = '' self.state = STATE_DISABLED # a dictionary with all direct neighbors # key is MAC for each neighbor # value is pair (age, mac, rloc16, role, rssi) #self.neigh_dict = {} self.router_data = RouterData() self.router_data.mac = self.MAC # a dictionary with all routers direct neighbors # key is MAC for each router # value is pair (age, rloc, neigh_num, (age, mac, rloc16, role, rssi)) #self.leader_dict = {} self.leader_data = LeaderData() self.leader_data.mac = self.MAC # set of all MACS from whole current Mesh Network self.macs = set() self.macs_ts = -65535 # very old # list of all pairs (direct radio connections) inside Mesh self.connections = list() self.connections_ts = -65535 # very old # set a new unicast address self._add_ipv6_unicast()
def __init__(self, filename): self.packsize = 400 # packsize self.buffer = bytearray(self.packsize) self.mv = memoryview(self.buffer) #self.ip = 0 # ip self.chunk = 0 self.filename = filename try: self.file = open(filename, "rb") except: print_debug(3, "File %s can't be opened !!!!"%filename) self.state = DONE return self.size = 0 self.start = time.time() self.state = INIT
def periodic_cb(self, alarm): # wait lock forever gc.collect() if self.lock.acquire(): print_debug(2, "============ MESH THREAD >>>>>>>>>>> ") t0 = time.ticks_ms() self.mesh.process() if self.mesh.is_connected(): # self.statistics.process() self.mesh.process_messages() # if Single Leader for 5 mins should reset if self.mesh.mesh.state == self.mesh.mesh.STATE_LEADER and self.mesh.mesh.mesh.single( ): if self.single_leader_ts == 0: # first time Single Leader, record time self.single_leader_ts = time.time() print("Single Leader", self.mesh.mesh.state, self.mesh.mesh.mesh.single(), time.time() - self.single_leader_ts) if time.time() - self.single_leader_ts > 300: print("Single Leader, just reset") self.mesh.mesh.mesh.deinit() # machine.reset() this might be causing nodes to boot loop if self.sleep_function: self.sleep_function(1) else: machine.reset() else: # print("Not Single Leader", self.mesh.mesh.state, self.mesh.mesh.mesh.single()) self.single_leader_ts = 0 self.lock.release() print_debug( 2, ">>>>>>>>>>> DONE MESH THREAD ============ %d\n" % (time.ticks_ms() - t0)) pass
def send_pack(self, pack_type, data, ip, port=PORT_MESH_INTERNAL): if self.sock is None: return False print_debug(3, "Send pack: 0x%X to IP %s" % (pack_type, ip)) # check not to send same (packet, destination) too often # if not self._check_to_send(pack_type, ip): # print_debug(3, "NO send") # return False sent_ok = True header = pack('!BH', pack_type, len(data)) try: self.sock.sendto(header + data, (ip, port)) #self.mesh.blink(2, .1) except Exception as ex: print_debug(3, "Socket.sendto exception: {}".format(ex)) sent_ok = False return sent_ok
def process(self): self.mesh.update_internals() self.mesh.led_state() print_debug(3, "%d: MAC %s(%d), State %s, Single %s" % (time.time(), hex(self.MAC), self.MAC, self.mesh.state_string(), str(self.mesh.mesh.single()))) print_debug(3, self.mesh.ipaddr()) leader = self.mesh.mesh.leader() if leader is not None: print_debug(3,"Leader: mac %s, rloc %s, net: %s" % (hex(leader.mac), hex(leader.rloc16), hex(leader.part_id))) if not self.mesh.is_connected(): return # nothing to do # create socket if self.sock is None: self.create_socket() if not self.rx_cb_registered: self.rx_cb_registered = True self.mesh.mesh.rx_cb(self.receive_all_data, None) # update internal neighbor table self.mesh.neighbors_update() self.mesh.leader_add_own_neigh() # # if file to be sent # if self.send_f is not None: # data, ip = self.send_f.process(None) # if len(data) > 0: # self.send_pack(self.PACK_FILE_SEND, data, ip) # if self.mesh.state == self.mesh.STATE_LEADER: # self._process_leader() return
def process(self, last_response): if self.state == INIT: self.chunk = self.file.readinto(self.buffer) self.state = WAIT_ACK self.retries = 0 self.size = self.chunk self.start = time.time() elif self.state == WAIT_ACK: if last_response is not None: # got ACK, send next chunk self.chunk = self.file.readinto(self.buffer) self.size = self.size + self.chunk print_debug(3, "%d Bytes sent, time: %4d sec" % (self.size, time.time() - self.start)) if self.chunk == 0: self._end_transfer() self.retries = 0 else: print_debug(3, "No answer, so retry?") if time.time() - self.last_ts < 5: #if we just sent the retry, don't resend anything, still wait for answer print_debug(3, "No retry, too soon") return '' self.retries = self.retries + 1 if self.retries > RETRIES_MAX: self._end_transfer() elif self.state == DONE: self.chunk = 0 self.last_ts = time.time() return self.mv[:self.chunk]
def routers_rloc_list(self, age_min, resolve_mac=None): """ return list of all routers IPv6 RLOC16 if mac parameter is present, then returns just the RLOC16 of that mac, if found """ mac_ip = None data = self.mesh.routers() print_debug(3, "Routers Table: " + str(data)) '''>>> print_debug(3, lora.cli('router table')) | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+-------+--------+-----+------------------+ | 12 | 0x3000 | 63 | 0 | 0 | 0 | 0 | 0000000000000002 |''' if data is None: # bad read return () net_addr = self.net_addr routers_list = [] for line in data: # line = (mac=123456, rloc16=20480, id=20, path_cost=0, age=7) age = line.age if age > 300: continue # shouldn't add/resolve very old Routers rloc16 = line.rloc16 # check if it's own rloc16 if rloc16 == self.rloc16: continue if resolve_mac is not None: if resolve_mac == line.mac: mac_ip = rloc16 break # look for this router in Leader Data # if doesn't exist, add it to routers_list with max ts # if it exists, just add it with its ts last_ts = self.leader_data.get_mac_ts(line.mac) if time.time() - last_ts < age_min: continue # shouldn't add/resolve very "recent" Routers ipv6 = net_addr + hex(rloc16)[2:] routers_list.append((last_ts, ipv6)) if resolve_mac is not None: print_debug(3, "Mac found in Router %s" % str(mac_ip)) return mac_ip # sort the list in the ascending values of timestamp routers_list.sort() print_debug(3, "Routers list %s" % str(routers_list)) return routers_list
def check_mac(pymesh_config, MAC): if pymesh_config.get('MAC') is None: # if MAC config unspecified, set it to LoRa MAC print_debug(3, "Set MAC in config file as " + str(MAC)) pymesh_config['MAC'] = MAC PymeshConfig.write_config(pymesh_config, False) else: mac_from_config = pymesh_config.get('MAC') if mac_from_config != MAC: print_debug(3, "MAC different" + str(mac_from_config) + str(MAC)) pymesh_config['MAC'] = MAC # if MAC in config different than LoRa MAC, set LoRa MAC as in config file fo = open("/flash/sys/lpwan.mac", "wb") mac_write = bytes([(MAC >> 56) & 0xFF, (MAC >> 48) & 0xFF, (MAC >> 40) & 0xFF, (MAC >> 32) & 0xFF, (MAC >> 24) & 0xFF, (MAC >> 16) & 0xFF, (MAC >> 8) & 0xFF, MAC & 0xFF]) fo.write(mac_write) fo.close() # print_debug(3, "reset") PymeshConfig.write_config(pymesh_config, False) print_debug(3, "MAC ok" + str(MAC))
def create_socket(self): """ create UDP socket """ self.sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.sock.bind(self.PORT_MESH_INTERNAL) print_debug(5, "Socket created on port %d" % self.PORT_MESH_INTERNAL)
def process(self, arg1, arg2): last_mesh_pairs = [] last_mesh_mac_list = [] last_mesh_node_info = {} try: while True: time.sleep(.1) cmd = input('>') if cmd == 'ip': print(self.mesh.ip()) elif cmd == 'mac': # read/write LoRa MAC address try: id = int( input('(new LoRa MAC (0-64k) [Enter for read])<')) except: print(self.mesh.mesh.mesh.MAC) continue id = id & 0xFFFF # just 2B value # it's actually set in main.py (main thread) print("LoRa MAC set to", id) self.sleep(1, id) # force restart elif cmd == 'mml': mesh_mac_list = self.mesh.get_mesh_mac_list() if len(mesh_mac_list) > 0: last_mesh_mac_list = mesh_mac_list print('mesh_mac_list ', json.dumps(last_mesh_mac_list)) elif cmd == 'self': node_info = self.mesh.get_node_info() print("self info:", node_info) elif cmd == 'mni': for mac in last_mesh_mac_list: node_info = self.mesh.get_node_info(mac) time.sleep(.5) if len(node_info) > 0: last_mesh_node_info[mac] = node_info print('last_mesh_node_info', json.dumps(last_mesh_node_info)) elif cmd == 'mp': mesh_pairs = self.mesh.get_mesh_pairs() if len(mesh_pairs) > 0: last_mesh_pairs = mesh_pairs print('last_mesh_pairs', json.dumps(last_mesh_pairs)) elif cmd == 's': try: to = int(input('(to)<')) # typ = input('(type, 0=text, 1=file, Enter for text)<') # if not typ: # typ = 0 # else: # typ = int(typ) txt = input('(message)<') except: continue data = { 'to': to, # 'ty': 0, 'b': txt, 'id': 12345, 'ts': int(time.time()), } print(self.mesh.send_message(data)) elif cmd == 'ws': to = int(input('(to)<')) try: id = int(input('(id, default 12345)<')) except: id = 12345 print(self.mesh.mesage_was_ack(to, id)) elif cmd == 'rm': print(self.mesh.get_rcv_message()) elif cmd == 'gps': try: lat = float(input('(lat [Enter for read])<')) lon = float(input('(lon)<')) except: print("Gps:", (Gps.lat, Gps.lon)) continue Gps.set_location(lat, lon) print("Gps:", (Gps.lat, Gps.lon)) elif cmd == 'sleep': try: timeout = int(input('(time[sec])<')) except: continue if self.sleep: self.sleep(timeout) # elif cmd == "ble": # # reset BLE connection # self.ble_comm.restart() # elif cmd == "stat": # # do some statistics # # data = [] # # data[0] = {'mac':6, 'n':3, 't':30, 's1':0, 's2':0} # # data[0] = {'mac':6, 'n':3, 't':30, 's1':5, 's2':10} # # data[2] = {'mac':6, 'n':30, 't':60, 's1':10, 's2':45} # # for line in data: # # print() # # print("1 = {'mac':6, 'n':30, 't':60, 's1':10, 's2':45}<'") # # print("2 = {'mac':6, 'n':30, 't':60, 's1':10, 's2':45}<'") # # print("3 = {'mac':6, 'n':30, 't':60, 's1':10, 's2':45}<'") # # id = int(input('(choice 1-..)<')) # data = {'mac':6, 'n':3, 't':60, 's1':3, 's2':8} # res = self.mesh.statistics_start(data) # print("ok? ", res) # elif cmd == "stat?": # try: # id = int(input('(id [Enter for all])<')) # except: # id = 0 # res = self.mesh.statistics_get(id) # print("ok? ", res) elif cmd == "rst": print("Mesh Reset NVM settings ... ") self.mesh.mesh.mesh.mesh.deinit() if self.sleep: self.sleep(1) # elif cmd == "pyb": # # print("Pybytes debug menu, Pybytes connection is ", Pybytes_wrap.is_connected()) # state = 1 # timeout = 120 # try: # state = int(input('(Debug 0=stop, 1=start [Default start])<')) # except: # pass # try: # timeout = int(input('(Pybytes timeout [Default 120 sec])<')) # except: # pass # self.mesh.pybytes_config((state == 1), timeout) elif cmd == "br": state = 2 # default display BR try: state = int( input( '(state 0=Disable, 1=Enable, 2=Display [Default Display])<' )) except: pass if state == 2: print("Border Router state: ", self.mesh.mesh.mesh.mesh.border_router()) elif state == 1: # Enable BR prio = 0 # default normal priority try: prio = int( input( '(priority -1=Low, 0=Normal or 1=High [Default Normal])<' )) except: pass self.mesh.br_set(True, prio, self.new_br_message_cb) else: # disable BR function self.mesh.br_set(False) elif cmd == "brs": """ send data to BR """ ip_default = "1:2:3::4" port = 5555 try: payload = input("(message<)") ip = input( "(IP destination, Mesh-external [Default: 1:2:3::4])<" ) if len(ip) == 0: ip = ip_default port = int( input("(port destination [Default: 5555])<")) except: pass data = {'ip': ip, 'port': port, 'b': payload} print("Send BR message:", data) self.mesh.send_message(data) elif cmd == "buf": print("Buffer info:", self.mesh.mesh.mesh.mesh.cli("bufferinfo")) elif cmd == "ot": cli = input('(openthread cli)<') print(self.mesh.mesh.mesh.mesh.cli(cli)) elif cmd == "debug": ret = input('(debug level[0-5])<') try: level = int(ret) self.mesh.debug_level(level) except: print_debug(1, "error parsing") elif cmd == "config": print(self.mesh.config) else: print("List of available commands") print("ip - display current IPv6 unicast addresses") print("mac - set or display the current LoRa MAC address") print("self - display all info about current node") print( "mml - display the Mesh Mac List (MAC of all nodes inside this Mesh), also inquires Leader" ) print( "mp - display the Mesh Pairs (Pairs of all nodes connections), also inquires Leader" ) print("s - send message") print("ws - verifies if message sent was acknowledged") print("rm - verifies if any message was received") print("sleep - deep-sleep") # print("stat - start statistics") # print("stat? - display statistics") print( "br - enable/disable or display the current Border Router functionality" ) print("brs - send packet for Mesh-external, to BR, if any") print("rst - reset NOW, including NVM Pymesh IPv6") print("buf - display buffer info") print("ot - sends command to openthread internal CLI") print("debug - set debug level") print("config - print config file contents") print("gps - get/set location coordinates") except KeyboardInterrupt: print('cli Got Ctrl-C') except Exception as e: sys.print_exception(e) finally: print('cli finally') self.sleep(0)
def receive_all_data(self, arg): """ receives all packages on socket """ while True: rcv_data, rcv_addr = self.sock.recvfrom(1024) if len(rcv_data) == 0: break # out of while, no packet rcv_ip = rcv_addr[0] rcv_port = rcv_addr[1] print_debug( 4, 'Incoming %d bytes from %s (port %d):' % (len(rcv_data), rcv_ip, rcv_port)) # print_debug(3, rcv_data) print_debug(5, str(self.mesh.lora.stats())) # check if Node is BR if self.br_handler: #check if data is for the external of the Pymesh (for Pybytes) if rcv_data[0] == self.BR_MAGIC_BYTE and len( rcv_data) >= calcsize(self.BR_HEADER_FMT): br_header = unpack(self.BR_HEADER_FMT, rcv_data) print_debug( 3, "BR pack, IP dest: %x:%x:%x:%x:%x:%x:%x:%x (port %d)" % (br_header[1], br_header[2], br_header[3], br_header[4], br_header[5], br_header[6], br_header[7], br_header[8], br_header[9])) rcv_data = rcv_data[calcsize(self.BR_HEADER_FMT):] dest_ip = "%x:%x:%x:%x:%x:%x:%x:%x" % ( br_header[1], br_header[2], br_header[3], br_header[4], br_header[5], br_header[6], br_header[7], br_header[8]) dest_port = br_header[9] print_debug(3, rcv_data) (type, rcv_data) = self.get_type(rcv_data) print_debug(3, rcv_data) self.br_handler(rcv_ip, rcv_port, rcv_data, dest_ip, dest_port) return # done, no more parsing as this pack was for BR # check packet type (type, rcv_data) = self.get_type(rcv_data) # LEADER if type == self.PACK_ROUTER_NEIGHBORS: print_debug(3, "PACK_ROUTER_NEIGHBORS received") self.mesh.routers_neigh_update(rcv_data) # no answer # elif type == self.PACK_ROUTER_ASK_LEADER_DATA: # print_debug(3, "PACK_ROUTER_ASK_LEADER_DATA received") # # send answer with Leader data # pack = self.mesh.leader_data_pack() # self.send_pack(self.PACK_LEADER_DATA, pack, rcv_ip) # ROUTER elif type == self.PACK_LEADER_ASK_NEIGH: print_debug(3, "PACK_LEADER_ASK_NEIGH received") payload = self.mesh.neighbors_pack() #time.sleep(.2) self.send_pack(self.PACK_ROUTER_NEIGHBORS, payload, rcv_ip) # elif type == self.PACK_LEADER_DATA: # print_debug(3, "PACK_LEADER_DATA received") # if self.mesh.leader_data_unpack(rcv_data): # self.interrogate_leader_ts = time.time() # ALL NODES elif type == self.PACK_MESSAGE: print_debug(3, "PACK_MESSAGE received") # add new pack received message = Message(rcv_data) # print_debug(3, message.payload) message.ip = rcv_ip self.messages.add_rcv_message(message) # send back ACK self.send_pack(self.PACK_MESSAGE_ACK, message.pack_ack(self.MAC), rcv_ip) # forward message to user-application layer if self.message_cb: self.message_cb(rcv_ip, rcv_port, message.payload) elif type == self.PACK_MESSAGE_ACK: print_debug(3, "PACK_MESSAGE_ACK received") # mark message as received self.messages.rcv_ack(rcv_data) elif type == self.PACK_ROUTER_ASK_MACS: print_debug(3, "PACK_ROUTER_ASK_MACS received") payload = self.mesh.leader_data.get_macs_pack() self.send_pack(self.PACK_LEADER_MACS, payload, rcv_ip) elif type == self.PACK_LEADER_MACS: print_debug(3, "PACK_LEADER_MACS received") self.mesh.macs_set(rcv_data) elif type == self.PACK_ROUTER_ASK_CONNECTIONS: print_debug(3, "PACK_ROUTER_ASK_CONNECTIONS received") payload = self.mesh.leader_data.get_connections_pack() self.send_pack(self.PACK_LEADER_CONNECTIONS, payload, rcv_ip) elif type == self.PACK_LEADER_CONNECTIONS: print_debug(3, "PACK_LEADER_CONNECTIONS received") self.mesh.connections_set(rcv_data) elif type == self.PACK_ROUTER_ASK_MAC_DETAILS: print_debug(3, "PACK_ROUTER_ASK_MAC_DETAILS received") (mac_req, ) = unpack('!H', rcv_data) print_debug(3, str(mac_req)) payload = self.mesh.leader_data.node_info_mac_pack(mac_req) if len(payload) > 0: self.send_pack(self.PACK_LEADER_MAC_DETAILS, payload, rcv_ip) else: print_debug(3, "No info found about MAC %d" % mac_req) elif type == self.PACK_LEADER_MAC_DETAILS: print_debug(3, "PACK_LEADER_MAC_DETAILS received") self.mesh.node_info_set(rcv_data) # elif type == self.PACK_FILE_SEND: # print_debug(3, "PACK_FILE_SEND received") # payload = pack("!Q", self.MAC) # self.send_pack(self.PACK_FILE_SEND_ACK, payload, rcv_ip) # # rcv data contains '!QHH' as header # chunk = len(rcv_data) -12 # self.file_size += chunk # print_debug(3, "size: %d, chunk %d" % (self.file_size, chunk)) # file_handler = "ab" # append, by default # if chunk > self.file_packsize: # # started receiving a new file # print_debug(3, "started receiving a new image") # file_handler = "wb" # write/create new file # self.file_packsize = chunk # elif chunk < self.file_packsize: # print_debug(3, "DONE receiving the image") # # done receiving the file # self.file_packsize = 0 # self.file_size = 0 # self.messages.file_transfer_done(rcv_data[:12]) # # else: # # #middle of the file, just write data # # self.file.write(rcv_data) # with open('/flash/dog_rcv.jpg', file_handler) as file: # file.write(rcv_data[12:]) # print_debug(3, "writing the image") # elif type == self.PACK_FILE_SEND_ACK: # mac_rcv = unpack("!Q", rcv_data) # print_debug(3, "PACK_FILE_SEND_ACK received from MAC %d"%mac_rcv) # mac_rcv = 6 # message = self.messages.dict.get(mac_rcv, None) # if message: # print_debug(3, "message found") # self.send_message(message, rcv_data) # else: # print_debug(3, "message NOT found ", mac_rcv, self.messages.dict) else: print_debug(3, "Unknown packet, type: 0x%X" % (type)) print_debug(3, str(rcv_data)) pass