Exemplo n.º 1
0
        /// <summary>
        /// constructor for message received (upstream)
        /// </summary>
        /// <param name="input"></param>
        public MacCommandHolder(byte[] input)
        {
            int pointer = 0;

            macCommand = new List <GenericMACCommand>();

            while (pointer < input.Length)
            {
                CidEnum cid = (CidEnum)input[pointer];
                switch (cid)
                {
                case CidEnum.LinkCheckCmd:
                    Logger.Log("mac command detected : LinkCheckCmd", Logger.LoggingLevel.Info);
                    LinkCheckCmd linkCheck = new LinkCheckCmd();
                    pointer += linkCheck.Length;
                    macCommand.Add(linkCheck);
                    break;

                case CidEnum.LinkADRCmd:
                    Logger.Log("mac command detected : LinkADRCmd", Logger.LoggingLevel.Info);
                    break;

                case CidEnum.DutyCycleCmd:
                    Logger.Log("mac command detected : DutyCycleCmd", Logger.LoggingLevel.Info);
                    DutyCycleCmd dutyCycle = new DutyCycleCmd();
                    pointer += dutyCycle.Length;
                    macCommand.Add(dutyCycle);
                    break;

                case CidEnum.RXParamCmd:
                    Logger.Log("mac command detected : RXParamCmd", Logger.LoggingLevel.Info);
                    break;

                case CidEnum.DevStatusCmd:
                    Logger.Log("mac command detected : DevStatusCmd", Logger.LoggingLevel.Info);
                    DevStatusCmd devStatus = new DevStatusCmd(input[pointer + 1], input[pointer + 2]);
                    pointer += devStatus.Length;
                    macCommand.Add(devStatus);
                    break;

                case CidEnum.NewChannelCmd:
                    Logger.Log("mac command detected : NewChannelCmd", Logger.LoggingLevel.Info);
                    NewChannelAns newChannel = new NewChannelAns(Convert.ToBoolean(input[pointer + 1] & 1), Convert.ToBoolean(input[pointer + 1] & 2));
                    pointer += newChannel.Length;
                    macCommand.Add(newChannel);
                    break;

                case CidEnum.RXTimingCmd:
                    Logger.Log("mac command detected : RXTimingCmd", Logger.LoggingLevel.Info);
                    RXTimingSetupCmd rXTimingSetup = new RXTimingSetupCmd();
                    pointer += rXTimingSetup.Length;
                    macCommand.Add(rXTimingSetup);
                    break;
                }
            }
        }
Exemplo n.º 2
0
        public MacCommandHolder(byte input)
        {
            macCommand = new List <GenericMACCommand>();

            CidEnum cid = (CidEnum)input;

            switch (cid)
            {
            case CidEnum.LinkCheckCmd:
                LinkCheckCmd linkCheck = new LinkCheckCmd();
                macCommand.Add(linkCheck);
                break;

            case CidEnum.LinkADRCmd:
                Logger.Log("mac command detected : LinkADRCmd", Logger.LoggingLevel.Info);
                break;

            case CidEnum.DutyCycleCmd:
                DutyCycleCmd dutyCycle = new DutyCycleCmd();
                macCommand.Add(dutyCycle);
                break;

            case CidEnum.RXParamCmd:
                Logger.Log("mac command detected : RXParamCmd", Logger.LoggingLevel.Info);
                break;

            case CidEnum.DevStatusCmd:
                Logger.Log("mac command detected : DevStatusCmd", Logger.LoggingLevel.Info);
                DevStatusCmd devStatus = new DevStatusCmd();
                macCommand.Add(devStatus);
                break;

            case CidEnum.NewChannelCmd:
                //NewChannelReq newChannel = new NewChannelReq();
                //macCommand.Add(newChannel);
                break;

            case CidEnum.RXTimingCmd:
                RXTimingSetupCmd rXTimingSetup = new RXTimingSetupCmd();
                macCommand.Add(rXTimingSetup);
                break;
            }
        }
        /// <summary>
        /// Create a List of Mac commands from server based on a sequence of bytes.
        /// </summary>
        public static List <MacCommand> CreateServerMacCommandFromBytes(string deviceId, ReadOnlyMemory <byte> input)
        {
            int pointer     = 0;
            var macCommands = new List <MacCommand>(3);

            while (pointer < input.Length)
            {
                try
                {
                    CidEnum cid = (CidEnum)input.Span[pointer];
                    switch (cid)
                    {
                    case CidEnum.LinkCheckCmd:
                        var linkCheck = new LinkCheckAnswer(input.Span.Slice(pointer));
                        pointer += linkCheck.Length;
                        macCommands.Add(linkCheck);
                        break;

                    case CidEnum.DevStatusCmd:
                        var devStatusRequest = new DevStatusRequest();
                        pointer += devStatusRequest.Length;
                        macCommands.Add(devStatusRequest);
                        break;

                    default:
                        Logger.Log(deviceId, $"a Mac command transmitted from the server, value ${input.Span[pointer]} was not from a supported type. Aborting Mac Command processing", LogLevel.Error);
                        return(null);
                    }

                    MacCommand addedMacCommand = macCommands[macCommands.Count - 1];
                    Logger.Log(deviceId, $"{addedMacCommand.Cid} mac command detected in upstream payload: {addedMacCommand.ToString()}", LogLevel.Debug);
                }
                catch (MacCommandException ex)
                {
                    Logger.Log(deviceId, ex.ToString(), LogLevel.Error);
                }
            }

            return(macCommands);
        }
Exemplo n.º 4
0
        internal static DownlinkMessageBuilderResponse CreateDownlinkMessage(
            NetworkServerConfiguration configuration,
            LoRaDevice loRaDevice,
            Region loRaRegion,
            IReceivedLoRaCloudToDeviceMessage cloudToDeviceMessage,
            uint fcntDown)
        {
            var fcntDownToSend = ValidateAndConvert16bitFCnt(fcntDown);

            // default fport
            byte    fctrl          = 0;
            CidEnum macCommandType = CidEnum.Zero;

            byte[] rndToken = new byte[2];

            lock (RndLock)
            {
                RndDownlinkMessageBuilder.NextBytes(rndToken);
            }

            bool isMessageTooLong = false;

            // Class C always uses RX2
            string datr;
            double freq;
            var    tmst = 0; // immediate mode

            // Class C always use RX2
            (freq, datr) = loRaRegion.GetDownstreamRX2DRAndFreq(loRaDevice.DevEUI, configuration.Rx2DataRate, configuration.Rx2DataFrequency, loRaDevice.ReportedRX2DataRate);

            // get max. payload size based on data rate from LoRaRegion
            var maxPayloadSize = loRaRegion.GetMaxPayloadSize(datr);

            // Deduct 8 bytes from max payload size.
            maxPayloadSize -= Constants.LORA_PROTOCOL_OVERHEAD_SIZE;

            var availablePayloadSize = maxPayloadSize;

            var macCommands = PrepareMacCommandAnswer(loRaDevice.DevEUI, null, cloudToDeviceMessage.MacCommands, null, null);

            // Calculate total C2D payload size
            var totalC2dSize = cloudToDeviceMessage.GetPayload()?.Length ?? 0;

            totalC2dSize += macCommands?.Sum(x => x.Length) ?? 0;

            // Total C2D payload will NOT fit
            if (availablePayloadSize < totalC2dSize)
            {
                isMessageTooLong = true;
                return(new DownlinkMessageBuilderResponse(null, isMessageTooLong));
            }

            if (macCommands?.Count > 0)
            {
                macCommandType = macCommands.First().Cid;
            }

            if (cloudToDeviceMessage.Confirmed)
            {
                loRaDevice.LastConfirmedC2DMessageID = cloudToDeviceMessage.MessageId ?? Constants.C2D_MSG_ID_PLACEHOLDER;
            }

            var frmPayload = cloudToDeviceMessage.GetPayload();

            if (Logger.LoggerLevel >= LogLevel.Information)
            {
                Logger.Log(loRaDevice.DevEUI, $"cloud to device message: {ConversionHelper.ByteArrayToString(frmPayload)}, id: {cloudToDeviceMessage.MessageId ?? "undefined"}, fport: {cloudToDeviceMessage.Fport}, confirmed: {cloudToDeviceMessage.Confirmed}, cidType: {macCommandType}", LogLevel.Information);
                Logger.Log(loRaDevice.DevEUI, $"sending a downstream message with ID {ConversionHelper.ByteArrayToString(rndToken)}", LogLevel.Information);
            }

            Array.Reverse(frmPayload);

            var payloadDevAddr  = ConversionHelper.StringToByteArray(loRaDevice.DevAddr);
            var reversedDevAddr = new byte[payloadDevAddr.Length];

            for (int i = reversedDevAddr.Length - 1; i >= 0; --i)
            {
                reversedDevAddr[i] = payloadDevAddr[payloadDevAddr.Length - (1 + i)];
            }

            var msgType        = cloudToDeviceMessage.Confirmed ? LoRaMessageType.ConfirmedDataDown : LoRaMessageType.UnconfirmedDataDown;
            var ackLoRaMessage = new LoRaPayloadData(
                msgType,
                reversedDevAddr,
                new byte[] { fctrl },
                BitConverter.GetBytes(fcntDownToSend),
                macCommands,
                new byte[] { cloudToDeviceMessage.Fport },
                frmPayload,
                1,
                loRaDevice.Supports32BitFCnt ? fcntDown : (uint?)null);

            return(new DownlinkMessageBuilderResponse(
                       ackLoRaMessage.Serialize(loRaDevice.AppSKey, loRaDevice.NwkSKey, datr, freq, tmst, loRaDevice.DevEUI),
                       isMessageTooLong));
        }
        /// <summary>
        /// Create a List of Mac commands from client based on a sequence of bytes.
        /// </summary>
        public static List <MacCommand> CreateMacCommandFromBytes(string deviceId, ReadOnlyMemory <byte> input)
        {
            int pointer     = 0;
            var macCommands = new List <MacCommand>(3);

            while (pointer < input.Length)
            {
                try
                {
                    CidEnum cid = (CidEnum)input.Span[pointer];
                    switch (cid)
                    {
                    case CidEnum.LinkCheckCmd:
                        var linkCheck = new LinkCheckRequest();
                        pointer += linkCheck.Length;
                        macCommands.Add(linkCheck);
                        break;

                    case CidEnum.LinkADRCmd:
                        var linkAdrAnswer = new LinkADRAnswer(input.Span.Slice(pointer));
                        pointer += linkAdrAnswer.Length;
                        macCommands.Add(linkAdrAnswer);
                        break;

                    case CidEnum.DutyCycleCmd:
                        var dutyCycle = new DutyCycleAnswer();
                        pointer += dutyCycle.Length;
                        macCommands.Add(dutyCycle);
                        break;

                    case CidEnum.RXParamCmd:
                        var rxParamSetup = new RXParamSetupAnswer(input.Span.Slice(pointer));
                        pointer += rxParamSetup.Length;
                        macCommands.Add(rxParamSetup);
                        break;

                    case CidEnum.DevStatusCmd:
                        // Added this case to enable unit testing
                        if (input.Length == 1)
                        {
                            var devStatusRequest = new DevStatusRequest();
                            pointer += devStatusRequest.Length;
                            macCommands.Add(devStatusRequest);
                        }
                        else
                        {
                            DevStatusAnswer devStatus = new DevStatusAnswer(input.Span.Slice(pointer));
                            pointer += devStatus.Length;
                            macCommands.Add(devStatus);
                        }

                        break;

                    case CidEnum.NewChannelCmd:
                        NewChannelAnswer newChannel = new NewChannelAnswer(input.Span.Slice(pointer));
                        pointer += newChannel.Length;
                        macCommands.Add(newChannel);
                        break;

                    case CidEnum.RXTimingCmd:
                        RXTimingSetupAnswer rxTimingSetup = new RXTimingSetupAnswer();
                        pointer += rxTimingSetup.Length;
                        macCommands.Add(rxTimingSetup);
                        break;

                    default:
                        Logger.Log(deviceId, $"a transmitted Mac Command value ${input.Span[pointer]} was not from a supported type. Aborting Mac Command processing", LogLevel.Error);
                        return(null);
                    }

                    MacCommand addedMacCommand = macCommands[macCommands.Count - 1];
                    Logger.Log(deviceId, $"{addedMacCommand.Cid} mac command detected in upstream payload: {addedMacCommand.ToString()}", LogLevel.Debug);
                }
                catch (MacCommandException ex)
                {
                    Logger.Log(deviceId, ex.ToString(), LogLevel.Error);
                }
            }

            return(macCommands);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MacCommandHolder"/> class.
        /// constructor for message received (upstream)
        /// </summary>
        public MacCommandHolder(byte[] input)
        {
            int pointer = 0;

            this.MacCommand = new List <GenericMACCommand>();

            while (pointer < input.Length)
            {
                CidEnum cid = (CidEnum)input[pointer];
                switch (cid)
                {
                case CidEnum.LinkCheckCmd:
                    Logger.Log("mac command detected : LinkCheckCmd", LogLevel.Information);
                    LinkCheckCmd linkCheck = new LinkCheckCmd();
                    pointer += linkCheck.Length;
                    this.MacCommand.Add(linkCheck);
                    break;

                case CidEnum.LinkADRCmd:
                    LinkADRCmd linkADRCmd = new LinkADRCmd();
                    pointer += linkADRCmd.Length;
                    this.MacCommand.Add(linkADRCmd);
                    Logger.Log("mac command detected : LinkADRCmd", LogLevel.Information);
                    break;

                case CidEnum.DutyCycleCmd:
                    Logger.Log("mac command detected : DutyCycleCmd", LogLevel.Information);
                    DutyCycleCmd dutyCycle = new DutyCycleCmd();
                    pointer += dutyCycle.Length;
                    this.MacCommand.Add(dutyCycle);
                    break;

                case CidEnum.RXParamCmd:
                    Logger.Log("mac command detected : RXParamCmd", LogLevel.Information);
                    RXParamSetupCmd rxParamSetupCmd = new RXParamSetupCmd();
                    pointer += rxParamSetupCmd.Length;
                    this.MacCommand.Add(rxParamSetupCmd);
                    break;

                case CidEnum.DevStatusCmd:
                    Logger.Log("mac command detected : DevStatusCmd", LogLevel.Information);
                    DevStatusCmd devStatus = new DevStatusCmd(input[pointer + 1], input[pointer + 2]);
                    pointer += devStatus.Length;
                    this.MacCommand.Add(devStatus);
                    break;

                case CidEnum.NewChannelCmd:
                    Logger.Log("mac command detected : NewChannelCmd", LogLevel.Information);
                    NewChannelAns newChannel = new NewChannelAns(Convert.ToBoolean(input[pointer + 1] & 1), Convert.ToBoolean(input[pointer + 1] & 2));
                    pointer += newChannel.Length;
                    this.MacCommand.Add(newChannel);
                    break;

                case CidEnum.RXTimingCmd:
                    Logger.Log("mac command detected : RXTimingCmd", LogLevel.Information);
                    RXTimingSetupCmd rXTimingSetup = new RXTimingSetupCmd();
                    pointer += rXTimingSetup.Length;
                    this.MacCommand.Add(rXTimingSetup);
                    break;

                default:
                    Logger.Log($"value {input[pointer]} as MAC command type is not recognized, aborting Mac command parsing", LogLevel.Error);
                    return;
                }
            }
        }