def update_lenddev(self, dev_eui, **kwargs): """Add new End Device.""" dev_eui = EUI64(dev_eui) desc = kwargs.get("desc", "Generic End Device") join_eui = EUI64(kwargs.get("joinEUI", "")) app_key = kwargs.get("appKey") nwk_key = kwargs.get("nwkKey") try: lenddev = self.lenddevs[dev_eui] except KeyError: raise KeyError("End Device %s not registered in \ the LNS Server" % dev_eui) if join_eui: lenddev.join_eui = join_eui if app_key: lenddev.app_key = app_key if nwk_key: lenddev.nwk_key = nwk_key if desc: lenddev.desc = desc lenddev.save() self.lenddevs[dev_eui] = lenddev return self.lenddevs[dev_eui]
def delete(self, *args, **kwargs): """Delete one or all LoRaWAN GTW from LSN Discovery Server. Args: [0]: the lnss euid [1]: the lgtw euid Example URLs: DELETE /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws DELETE /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws/ b827:ebff:fee7:7681 """ lns_euid = None lgtw_euid = None if args[0]: lns_euid = EUI64(args[0]) if len(args) == 2: if args[1]: lgtw_euid = EUI64(args[1]) if len(args) == 2 and lns_euid and lgtw_euid: self.service.remove_lgtw(lgtw_euid, lns_euid) elif len(args) == 2 and not lns_euid and lgtw_euid: self.service.remove_lgtw(lgtw_euid) elif lns_euid: for lgtw_euid in self.service.lgtws: self.service.remove_lgtw(lgtw_euid, lns_euid) else: for lns_euid in self.service.lnss: for lgtw_euid in self.service.lgtws: self.service.remove_lgtw(lgtw_euid, lns_euid)
def _handle_jreq(self, join_msg, rxtime): """Handle an incoming Join Request from a device. Args: join_msg, a JOIN message Returns: None """ data = {} data["radio_data"] = self._handle_radio_data(join_msg, rxtime) data["rxtime"] = rxtime data["join_data"] = {} try: data["join_data"]["MHdr"] = join_msg["MHdr"] data["join_data"]["JoinEui"] = EUI64(join_msg["JoinEui"]) data["join_data"]["DevEui"] = EUI64(join_msg["DevEui"]) data["join_data"]["DevNonce"] = join_msg["DevNonce"] data["join_data"]["MIC"] = join_msg["MIC"] & (2**32 - 1) data["xtime"] = join_msg['upinfo']["xtime"] # internal time of the lGTW data["rctx"] = join_msg['upinfo']["rctx"] # specifies the antenna used except KeyError as err: LOG.info("Malformed Join Request") LOG.info(err) else: data["PhyPayload"] = struct.pack("<BQQHI", join_msg["MHdr"], int(data["join_data"]["JoinEui"]), int(data["join_data"]["DevEui"]), # TODO check if int(value,16) # is needed # int(data["join_data"]["JoinEui"], # 16), # int(data["join_data"]["DevEui"], # 16), join_msg["DevNonce"] & 0xFFFF, join_msg["MIC"] & (2**32 - 1)).hex() if data["join_data"]["DevEui"] in self.server.lenddevs: LOG.info(data["join_data"]) # TODO implementation of Join Data handling else: LOG.info("Device %s is not in the database", data["join_data"]["DevEui"]) # Call registered callbacks data["msg"] = join_msg self.call_registered_callbacks(lnsp.PT_JOIN_REQ, **data)
def update_lgtw(self, lgtw_euid, **kwargs): """Update lGTW in the LNS database.""" lgtw_euid = EUI64(lgtw_euid) desc = kwargs.get("desc") name = kwargs.get("name") owner = str(kwargs.get("owner")) lgtw_config = kwargs.get("lgtw_config") if lgtw_euid not in self.lgtws: raise ValueError("GTW %s not registered in the \ LNS Server" % lgtw_euid) try: lgtw = self.lgtws[lgtw_euid] except KeyError: raise KeyError("%s not registered, \ register lgtw first" % lgtw_euid) if owner: lgtw.owner = owner if name: lgtw.name = name if desc: lgtw.desc = desc if lgtw_config: lgtw.lgtw_config = lgtw_config self.lgtws[lgtw_euid] = lgtw.save() return self.lgtws[lgtw_euid]
def post(self, *args, **kwargs): """Add a new LNS to the LNS Discovery Server Database. Request: version: protocol version (1.0) euid: the lns id in eui64 or euid format (mandatory) uri: the lns uri template (mandatory) desc: a human readable description of the device (optional) lgtws: the of lGTWS (optional) Example URLs: POST /api/v1/lnsd/lnss/"::1" { "version":"1.0", "euid": "0000:0000:0000:0001", "lgtws":["b827:ebff:fee7:7681"], "uri":"ws://0.0.0.0:6038/router-", "desc": "Generic LNS" } """ kwargs['euid'] = EUI64(kwargs['euid']) lnss = self.service.add_lns(**kwargs) self.set_header("Location", "/api/v1/lnsd/lnss/%s" % lnss.euid)
def put(self, *args, **kwargs): """Add a new LNS to the LNS Discovery Server Database. Args: [0]: the lns id in eui64 or euid format (mandatory) Request: version: protocol version (1.0) uri: the lns uri template (mandatory) desc: a human readable description of the device (optional) lgtws: the of lGTWS (optional) Example URLs: PUT /api/v1/lnsd/lnss/::1 { "version":"1.0", "lgtws":["b827:ebff:fee7:7681"], "uri":"ws://0.0.0.0:6038/router-", "desc": "Generic LNS" } """ self.service.update_lns(euid=EUI64(args[0]), **kwargs)
def open(self, *args: str, **kwargs: str): """Exec code when a new WebSocket is opened. The arguments to `open` are extracted from the `tornado.web.URLSpec` regular expression, just like the arguments to `tornado.web.RequestHandler.get`. """ lgtw_euid = EUI64(args[0]) try: self.lgtw = self.server.lgtws[lgtw_euid] except KeyError: LOG.info("Unregistered lGtw (%s), closing connection", lgtw_euid) self.close() return # save lGTW IP address self.lgtw.ipaddr = self.request.remote_ip self.lgtw.last_seen_ts = datetime.now().timestamp() self.lgtw.save() # REVIEW test # save lGTW connection self.lgtw.connection = self # set lGTW state to CONNECTED self.lgtw.set_connected() LOG.info("Connected to lGtw %s", self.lgtw.lgtw_euid.id6)
def get(self, *args, **kwargs): """List LoRaWAN End devices. Args: [0]: devEUI (optional) Example URLs: GET /api/v1/lns/lenddevs [ { "devEUI": "0028A154B89172D2" "devAddr": "0028A154B89172D2", "desc": "End Device XXX" } ] GET /api/v1/lns/lenddevs/00:28:A1:54:B8:91:72:D2 { "devAddr": "0028A154B89172D2", "desc": "End Device XXX" } """ if not args: out = [] for key in self.service.lenddevs: out.append(self.service.lenddevs[key].to_dict()) return out dev_eui = EUI64(args[0]) print(self.service.lenddevs) return self.service.lenddevs[dev_eui].to_dict()
def remove_lgtw(self, lgtw_euid): """Remove GTW from LNS database.""" lgtw_euid = EUI64(lgtw_euid) if lgtw_euid not in self.lgtws: raise KeyError("GTW %s not registered" % lgtw_euid) lgtw = self.lgtws[lgtw_euid] lgtw.delete() del self.lgtws[lgtw_euid]
def remove_lenddev(self, dev_eui): """Remove End Device.""" dev_eui = EUI64(dev_eui) if dev_eui not in self.lenddevs: raise KeyError("End Device %s not registered" % dev_eui) lenddev = self.lenddevs[dev_eui] lenddev.delete() del self.lenddevs[dev_eui]
def get(self, *args, **kwargs): """List LoRaWAN Gateways. Args: [0]: the LoRaWAN Gateway EUID (optional) Example URLs: GET /api/v1/lns/lgtws [ {"lgtw_euid": "b8:27:eb:ff:fe:e7:76:81", "desc": "iC880A Concentrator", "state": "disconnected", "owner": "00:00:00:00:00:00:00:00", "lgtw_version": [...], "lgtw_config": [...], "last_seen": "2020-02-18 12:40:52", "last_seen_ts": 1582026052.0, "connection": null}, {[...]}, ] GET /api/v1/lns/lgtws/b8:27:eb:ff:fe:e7:76:81 { "lgtw_euid": "b8:27:eb:ff:fe:e7:76:81", "desc": "iC880A Concentrator", "state": "disconnected", "owner": "00:00:00:00:00:00:00:00", "lgtw_version": [...], "lgtw_config": [...], "last_seen": "2020-02-18 12:40:52", "last_seen_ts": 1582026052.0, "connection": null } """ out = [] desc = self.get_argument("desc", None) name = self.get_argument("name", None) if len(args) == 1: lgtw_euid = EUI64(args[0]) if lgtw_euid in self.service.lgtws: lgtw = self.service.lgtws[lgtw_euid].to_dict() if not ((desc and (desc not in lgtw["desc"])) or (name and (name not in lgtw["name"]))): out = [lgtw] return out for key in self.service.lgtws: if (desc and desc not in self.service.lgtws[key].to_dict()["desc"]): continue if (name and name not in self.service.lgtws[key].to_dict()["name"]): continue out.append(self.service.lgtws[key].to_dict()) return out
def add_lenddev(self, dev_eui, **kwargs): """Add new End Device.""" dev_eui = EUI64(dev_eui) if dev_eui in self.lenddevs: raise ValueError( "End Device %s already registered in the LNS Server" % dev_eui) kwargs["dev_eui"] = dev_eui lenddev = LoRaWANEndDev(**kwargs).save() self.lenddevs[dev_eui] = lenddev return self.lenddevs[dev_eui]
def add_lns(self, euid, uri, lgtws, desc="Generic LNS"): """Add a new LNS. Overwrites LNS if it already exists.""" if euid in self.lnss: raise ValueError("LNS %s already defined" % euid) lgtws = [EUI64(lgtw).id6 for lgtw in lgtws] lns = LNS(uri=uri, euid=euid, desc=desc, lgtws=lgtws).save() self.lnss[euid] = lns return self.lnss[euid]
def post(self, *args, **kwargs): """Add a new LoRaWAN GTW to the LNS Discovery Server Database. Args: [0]: the lnss euid (mandatory) [1]: the lgtw euid (mandatory) Example URLs: POST /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws/ b827:ebff:fee7:7681 """ lns_euid = EUI64(args[0]) lgtw_euid = EUI64(args[1]) self.service.add_lgtw(lns_euid=lns_euid, lgtw_euid=lgtw_euid) self.set_header( "Location", "/api/v1/lnsd/lnss/%s/lgtws/%s" % (lns_euid, lgtw_euid))
def update_lns(self, euid, uri, lgtws, desc="Generic LNS"): """Update LNS data.""" lns = self.lnss[euid] try: lns.uri = uri lns.desc = desc lns.lgtws = [EUI64(lgtw) for lgtw in lgtws] lns.save() finally: lns.refresh_from_db() return self.lnss[euid]
def delete(self, *args, **kwargs): """Delete one or all LoRaWAN end devices. Args: [0]: the lGTW euid Example URLs: DELETE /api/v1/lns/lgtws DELETE /api/v1/lns/lgtws/08:27:eb:ff:fe:e7:76:91 """ if args: self.service.remove_lgtw(EUI64(args[0])) else: self.service.remove_all_lgtws()
def delete(self, *args, **kwargs): """Delete one or all LoRaWAN end devices. Args: [0]: devEUI Example URLs: DELETE /api/v1/lns/lenddevs DELETE /api/v1/lns/lenddevs/00:28:A1:54:B8:91:72:D2 """ if args: self.service.remove_lenddev(EUI64(args[0])) else: self.service.remove_all_lenddevs()
def handle_message(self, msg): """Handle incoming message.""" try: self.lgtw_id = EUI64(msg['router']) except KeyError: LOG.error("Bad message formatting, 'router' information" "(Radio GTW EUI) missing") return LOG.info("New LNS discovery request from %s: %s", self.lgtw_id, json.dumps(msg)) self.send_lns_discovery_request_replay() return
def add_lns(self, euid, uri, lgtws=None, desc="Generic LNS"): """Add a new LNS.""" if euid in self.lnss: raise ValueError("LNS %s already defined" % euid) if not lgtws: lgtws = [] else: lgtws = [EUI64(lgtw).id6 for lgtw in lgtws] lns = LNS(uri=uri, euid=euid, desc=desc, lgtws=lgtws).save() self.lnss[euid] = lns return self.lnss[euid]
def delete(self, *args, **kwargs): """Delete one or all devices. Args: [0]: the lns id in eui64 or euid format (optional) Example URLs: DELETE /api/v1/lnsd/lnss DELETE /api/v1/lnsd/lnss/::1 """ if args: self.service.remove_lns(EUI64(args[0])) else: self.service.remove_all_lnss()
def update_lns(self, euid, uri, lgtws=None, desc="Generic LNS"): """Update LNS data.""" lns = self.lnss[euid] if not lgtws: lgtws = [] else: lgtws = [EUI64(lgtw).id6 for lgtw in lgtws] try: lns.uri = uri lns.desc = desc lns.lgtws = lgtws lns.save() finally: lns.refresh_from_db() return self.lnss[euid]
def add_lgtw(self, lgtw_euid, **kwargs): """Add lGTW to LNS database.""" lgtw_euid = EUI64(lgtw_euid) name = kwargs.get("name", "BasicStation") desc = kwargs.get("desc", "Generic GTW") owner = str(kwargs.get("owner", lnsp.DEFAULT_OWNER)) lgtw_config = kwargs.get("lgtw_config", self.lgtw_settings) if lgtw_euid in self.lgtws: raise ValueError("GTW %s already registered in the LNS Server" % lgtw_euid) self.lgtws[lgtw_euid] = LoRaWANgtw(lgtw_euid=lgtw_euid, desc=desc, owner=owner, name=name, lgtw_config=lgtw_config).save() return self.lgtws[lgtw_euid]
def get(self, *args, **kwargs): """List devices. Args: [0]: the lns euid (optional) Example URLs: GET /api/v1/lnsd/lnss [ { "euid": "0000:0000:0000:0001", "desc": "Generic LNS", "uri": "ws://0.0.0.0:6038/router-", "lgtws": [ "b827:ebff:fee7:7681" ], "last_seen": 0, "last_seen_ts": "1970-01-01T01:00:00.000000Z", "period": 0 } ] GET /api/v1/lnsd/lnss/::1 { "euid": "0000:0000:0000:0001", "desc": "Generic LNS", "uri": "ws://0.0.0.0:6038/router-", "lgtws": [ "b827:ebff:fee7:7681" ], "last_seen": 0, "last_seen_ts": "1970-01-01T01:00:00.000000Z", "period": 0 } """ return self.service.lnss \ if not args else self.service.lnss[EUI64(args[0])]
def handle_add_lgtw(self, euid): """Save whe the lEndDev is seen by a new lGTW.""" if str(EUI64(euid)) not in self.lgtws_range: self.lgtws_range.append(euid)
def get(self, *args, **kwargs): """List devices. Args: [0]: the lnss euid (optional) [1]: the lgtw euid (optional) Example URLs: GET /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws { "lns_euid": "0000000000000001", "lgtw_euid": [ "b827ebfffee77681" ] } GET /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws/b827:ebff:fee7:7681 { "lns_euid": "0000000000000001", "lgtw_euid": "b827ebfffee77681" } """ lns_euid = args[0] lgtw_euid = args[1] if len(args) == 2 else None out = [] if lns_euid: lns_euid = EUI64(lns_euid) if lgtw_euid: lgtw_euid = EUI64(args[1]) if not lns_euid and not lgtw_euid: # E.g. GET /api/v1/lnsd/lnss//lgtws/ for key in self.service.lnss: out.append({ "lns_euidx": EUI64(key), "lgtw_euids": self.service.lnss[key].lgtws }) elif (lns_euid in self.service.lnss and lgtw_euid in self.service.lnss[lns_euid].lgtws): # E.g. GET # /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws/b827:ebff:fee7:7681 out = {"lns_euid": lns_euid, "lgtw_euid": lgtw_euid} elif lns_euid in self.service.lnss and not lgtw_euid: # E.g. # GET /api/v1/lnsd/lnss/0000:0000:0000:0001/lgtws/ out = { "lns_euid": lns_euid, "lgtw_euid": self.service.lnss[lns_euid].lgtws } elif not lns_euid and lgtw_euid in self.service.lgtws: # E.g. # GET /api/v1/lnsd/lnss//lgtws/b827:ebff:fee7:7681 for key in self.service.lgtws[lgtw_euid]: out.append({"lns_euid": EUI64(key), "lgtw_euid": [lgtw_euid]}) else: raise KeyError("Unable to find pair (%s, %s)" % (lns_euid, lgtw_euid)) return out