def _sendLinkADRRequest(self, device, command): """Send a Link ADR Request message Called if an ADR change is required for this device. Args: device: (Device): Target device command (LinkADRReq): Link ADR Request object """ frmpayload = command.encode() # Create the downlink message. Increment fcntdown, set fport=0, # encrypt with NwkSKey and encode fcntdown = device.fcntdown + 1 log.info("Sending ADR Request to devaddr {devaddr}", devaddr=devaddrString(device.devaddr)) message = MACDataDownlinkMessage(device.devaddr, device.nwkskey, fcntdown, self.config.adrenable, '', 0, frmpayload) message.encrypt(device.nwkskey) data = message.encode() gateway = self.lora.gateway(device.gw_addr) if gateway is None: log.info( "Could not find gateway for gateway {gw_addr} for device " "{devaddr}", gw_addr=device.gw_addr, devaddr=devaddrString(device.devaddr)) returnValue(None) # Create GatewayMessage and Txpk objects, send immediately request = GatewayMessage(version=1, token=0, remote=(gateway.host, gateway.port)) device.rx = self.band.rxparams((device.tx_chan, device.tx_datr)) txpk = self._txpkResponse(device, data, gateway, immediate=True) # Update the device fcntdown device.update(fcntdown=fcntdown) # Send the RX2 window message self.lora.sendPullResponse(request, txpk[2])
def inboundAppMessage(self, devaddr, appdata, acknowledge=False): """Sends inbound data from the application interface to the device Args: devaddr (int): 32 bit device address (DevAddr) appdata (str): packed application data acknowledge (bool): Acknowledged message """ log.info("Inbound message to devaddr {devaddr}", devaddr=devaddrString(devaddr)) # Retrieve the active device device = yield self._getActiveDevice(devaddr) if device is None: log.error("Cannot send to unregistered device address {devaddr}", devaddr=devaddrString(devaddr)) returnValue(None) # Check the device is enabled if not device.enabled: log.error( "Inbound application message for disabled device " "{deveui}", deveui=euiString(device.deveui)) returnValue(None) # Get the associated application app = yield Application.find(where=['appeui = ?', device.appeui], limit=1) if app is None: log.error( "Inbound application message for {deveui} - " "AppEUI {appeui} does not match any configured applications.", deveui=euiString(device.deveui), appeui=device.appeui) returnValue(None) # Find the gateway gateway = self.lora.gateway(device.gw_addr) if gateway is None: log.error( "Could not find gateway for inbound message to " "{devaddr}.", devaddr=devaddrString(device.devaddr)) returnValue(None) # Increment fcntdown fcntdown = device.fcntdown + 1 # Piggyback any queued MAC messages in fopts fopts = '' device.rx = self.band.rxparams((device.tx_chan, device.tx_datr), join=False) if self.config.macqueueing: # Get all of this device's queued commands: this returns a list of tuples (index, command) commands = [(i, c[2]) for i, c in enumerate(self.commands) if device.deveui == c[1]] for (index, command) in commands: # Check if we can accommodate the command. If so, encode and remove from the queue if self.band.checkAppPayloadLen(device.rx[1]['datr'], len(fopts) + len(appdata)): fopts += command.encode() del self.commands[index] else: break # Create the downlink message, encrypt with AppSKey and encode response = MACDataDownlinkMessage(device.devaddr, device.nwkskey, device.fcntdown, self.config.adrenable, fopts, int(app.fport), appdata, acknowledge=acknowledge) response.encrypt(device.appskey) data = response.encode() # Create Txpk objects txpk = self._txpkResponse(device, data, gateway, itmst=int(device.tmst), immediate=False) request = GatewayMessage(version=2, gatewayEUI=gateway.eui, remote=(gateway.host, gateway.port)) # Save the frame count down device.update(fcntdown=fcntdown) # Send RX1 window message self.lora.sendPullResponse(request, txpk[1]) # If Class A, send the RX2 window message self.lora.sendPullResponse(request, txpk[2])