def get(self, appinterface_id): """Method to handle application GET requests Args: appinterface_id (int): Application Interface ID """ try: interface = interfaceManager.getInterface(appinterface_id) # Return a 404 if not found. if interface is None: abort(404, message={ 'error': "Application interface id {} " "doesn't exist.".format(str(appinterface_id)) }) # Return the interface's marshalled attributes returnValue(interface.marshal()) yield except TimeoutError: log.error( "REST API timeout retrieving application interface " "{id}", id=appinterface_id)
def delete(self, appinterface_id): """Method to handle AppInterface DELETE requests Args: appinterface_id (int): Application inetrface id """ try: # Check that no interfaces exist with this interface_id. interface = yield interfaceManager.getInterface(appinterface_id) if interface is None: abort(404, message={ 'error': "Interface {} doesn't exist.".format( str(appinterface_id)) }) # Delete the interface via interfaceManager yield interfaceManager.deleteInterface(interface) returnValue(({}, 200)) except TimeoutError: log.error( "REST API timeout retrieving application interface " "{id}", id=appinterface_id)
def put(self, appinterface_id): """Method to handle AppInterface PUT requests Args: appinterface_id (int): Application Interface ID """ try: interface = interfaceManager.getInterface(appinterface_id) # Return a 404 if not found. if interface is None: abort(404, message={ 'error': "Application interface id {} " "doesn't exist.".format(str(appinterface_id)) }) kwargs = {} for a, v in self.args.items(): if hasattr(interface, a) and v is not None and v != getattr(interface, a): kwargs[a] = v setattr(interface, a, v) (valid, message) = yield interface.valid() if not valid: abort(400, message=message) # Update the interface via interfaceManager if kwargs: yield interfaceManager.updateInterface(interface) returnValue(({}, 200)) except TimeoutError: log.error( "REST API timeout retrieving application interface " "{id}", id=appinterface_id)
def processPushDataMessage(self, request, gateway): """Process a PUSH_DATA message from a LoraWAN gateway Args: request (GatewayMessage): the received gateway message object gateway (Gateway): the gateway that sent the message Returns: True on success, otherwise False """ if not request.rxpk: request.rxpk = [] for rxpk in request.rxpk: # Decode the MAC message message = MACMessage.decode(rxpk.data) if message is None: log.info( "MAC message decode error for gateway {gateway}: message " "timestamp {timestamp}", gateway=gateway.host, timestamp=str(rxpk.time)) returnValue(False) # Check if thisis a duplicate message if self._checkDuplicateMessage(message): returnValue(False) # Join Request if message.isJoinRequest(): # Get the application using appeui app = yield Application.find( where=['appeui = ?', message.appeui], limit=1) #app = next((a for a in self.applications if # a.appeui == message.appeui), None) if app is None: log.info( "Message from {deveui} - AppEUI {appeui} " "does not match any configured applications.", deveui=euiString(message.deveui), appeui=message.appeui) returnValue(False) # Find the Device device = yield Device.find( where=['deveui = ?', message.deveui], limit=1) if device is None: #log.info("Message from unregistered device {deveui}", # deveui=euiString(message.deveui)) #returnValue(False) # TODO save device to database (cheng) device = Device(deveui=message.deveui, name='smk_node', devclass='A', enabled=True, otaa=True, devaddr=None, devnonce=[], appeui=message.appeui, nwkskey='', appskey='', fcntup=0, fcntdown=0, fcnterror=False, snr=[], snr_average=0) #device.save() else: # Check the device is enabled if not device.enabled: log.info("Join request for disabled device {deveui}.", deveui=euiString(device.deveui)) returnValue(False) # Process join request joined = yield self._processJoinRequest(message, app, device) if joined: # Update the ADR measures if self.config.adrenable: device.updateSNR(rxpk.lsnr) yield device.update(tx_chan=rxpk.chan, tx_datr=rxpk.datr, devaddr=device.devaddr, nwkskey=device.nwkskey, appskey=device.appskey, time=rxpk.time, tmst=rxpk.tmst, gw_addr=gateway.host, fcntup=0, fcntdown=0, fcnterror=False, devnonce=device.devnonce, snr=device.snr, snr_average=device.snr_average) log.info( "Successful Join request from DevEUI {deveui} " "for AppEUI {appeui} | Assigned address {devaddr}", deveui=euiString(device.deveui), appeui=euiString(app.appeui), devaddr=devaddrString(device.devaddr)) # Send the join response device.save() self._sendJoinResponse(request, rxpk, gateway, app, device) returnValue(True) else: log.info( "Could not process join request from device " "{deveui}.", deveui=euiString(device.deveui)) returnValue(False) # LoRa message. Check this is a registered device device = yield self._getActiveDevice(message.payload.fhdr.devaddr) if device is None: log.info( "Message from device using unregistered address " "{devaddr}", devaddr=devaddrString(message.payload.fhdr.devaddr)) returnValue(False) # Check the device is enabled if not device.enabled: log.info("Message from disabled device {devaddr}", devaddr=devaddrString(message.payload.fhdr.devaddr)) returnValue(False) # Check frame counter if not device.checkFrameCount(message.payload.fhdr.fcnt, self.band.max_fcnt_gap, self.config.fcrelaxed): log.info("Message from {devaddr} failed frame count check.", devaddr=devaddrString(message.payload.fhdr.devaddr)) log.debug( "Received frame count {fcnt}, device frame count {dfcnt}", fcnt=message.payload.fhdr.fcnt, dfcnt=device.fcntup) yield device.update(fcntup=device.fcntup, fcntdown=device.fcntdown, fcnterror=device.fcnterror) returnValue(False) # Perform message integrity check. if not message.checkMIC(device.nwkskey): log.info( "Message from {devaddr} failed message " "integrity check.", devaddr=devaddrString(message.payload.fhdr.devaddr)) returnValue(False) # Update SNR reading and device device.updateSNR(rxpk.lsnr) yield device.update(tx_chan=rxpk.chan, tx_datr=rxpk.datr, fcntup=device.fcntup, fcntdown=device.fcntdown, fcnterror=device.fcnterror, time=rxpk.time, tmst=rxpk.tmst, adr=bool(message.payload.fhdr.adr), snr=device.snr, snr_average=device.snr_average, gw_addr=gateway.host) # Set the device rx window parameters device.rx = self.band.rxparams((device.tx_chan, device.tx_datr), join=False) # Process MAC Commands commands = [] # Standalone MAC command if message.isMACCommand(): message.decrypt(device.nwkskey) commands = [MACCommand.decode(message.payload.frmpayload)] # Contains piggybacked MAC command(s) elif message.hasMACCommands(): commands = message.commands for command in commands: if command.isLinkCheckReq(): self._processLinkCheckReq(device, command, request, rxpk.lsnr) elif command.isLinkADRAns(): self._processLinkADRAns(device, command) # TODO: add other MAC commands # Process application data message if message.isUnconfirmedDataUp() or message.isConfirmedDataUp(): # Find the app app = yield Application.find( where=['appeui = ?', device.appeui], limit=1) if app is None: log.info( "Message from {devaddr} - AppEUI {appeui} " "does not match any configured applications.", devaddr=euiString(device.devaddr), appeui=device.appeui) returnValue(False) # Decrypt frmpayload message.decrypt(device.appskey) appdata = str(message.payload.frmpayload) port = message.payload.fport # Route the data to an application server via the configured interface log.info("Outbound message from devaddr {devaddr}", devaddr=devaddrString(device.devaddr)) interface = interfaceManager.getInterface(app.appinterface_id) if interface is None: log.error( "No outbound interface found for application " "{app}", app=app.name) elif not interface.started: log.error( "Outbound interface for application " "{app} is not started", app=app.name) else: self._outboundAppMessage(interface, device, app, port, appdata) # Send an ACK if required if message.isConfirmedDataUp(): yield self.inboundAppMessage(device.devaddr, '', acknowledge=True)