Esempio n. 1
0
 async def ncr_optdr(m:lm.Msg, freq:int) -> lm.Msg:
     self.lw_dnlink(m, port=0, payload=lo.pack_opts(
         [lo.NewChannelReq(Chnl=3, Freq=freq//100, MinDR=0, MaxDR=7)]))
     m = await self.lw_uplink()
     opts = self.get_opts(m)
     self.assert_equals(len(opts), 1)
     self.check_ncr_o(opts[0])
     return m
Esempio n. 2
0
 async def ncr_optdr(m:LoraWanMsg, freq:int, msg:str) -> LoraWanMsg:
     dut.dndf(m, 0, lo.pack_opts([lo.NewChannelReq(Chnl=3, Freq=freq//100, MinDR=0, MaxDR=7)]))
     m = await dut.updf(explain=msg)
     opts = m.unpack_opts()
     assert len(opts) == 1, msg
     opt, = opts
     dut.check_ncr_o(opt, explain=msg)
     return m
Esempio n. 3
0
        async def ncr_add(m:lm.Msg, chans:List[Tuple[int,int]]) -> lm.Msg:
            opts = [lo.NewChannelReq(Chnl=ch, Freq=f//100, MinDR=0, MaxDR=5)
                    for ch, f in chans]
            self.lw_dnlink(m, port=0, payload=lo.pack_opts(opts))

            m = await self.lw_uplink()
            opts = self.get_opts(m)
            self.assert_equals(len(opts), len(chans))
            for i,o in enumerate(opts):
                if chans[i][0] < len(self.region.upchannels):
                    self.check_ncr_o(o, ChnlAck=0, DRAck=None)
                else:
                    self.check_ncr_o(o)

            return await self.check_freqs(m, frozenset(it.chain(
                (ch[1] for ch in chans if ch[1]),
                (ch.freq for ch in self.region.upchannels))))
Esempio n. 4
0
    async def ncr_add(m:LoraWanMsg, chans:List[Tuple[int,int]]) -> LoraWanMsg:
        opts = [lo.NewChannelReq(Chnl=ch, Freq=f//100, MinDR=0, MaxDR=5)
                for ch, f in chans]
        dut.dndf(m, 0, lo.pack_opts(opts))

        m = await dut.test_updf()
        opts = m.unpack_opts()
        assert len(opts) == len(chans)
        for i, o in enumerate(opts):
            if chans[i][0] < len(dut.session['region'].upchannels):
                dut.check_ncr_o(o, ChnlAck=0, DRAck=None)
            else:
                dut.check_ncr_o(o)

        return await dut.check_freqs(m, frozenset(itertools.chain(
            (ch[1] for ch in chans if ch[1]),
            (ch.freq for ch in dut.session['region'].upchannels))))
Esempio n. 5
0
    async def link_adr_req(self) -> bool:
        def check_laa(m: lm.Msg, explain: Optional[str] = None) -> None:
            opts = self.get_opts(m)
            self.assert_equals(len(opts), 1, explain)
            self.check_laa_o(opts[0], explain=explain)

        def check_laa_block(m: lm.Msg,
                            n: int,
                            ChAck: Optional[int] = 1,
                            DRAck: Optional[int] = 1,
                            TXPowAck: Optional[int] = 1,
                            explain: Optional[str] = None) -> None:
            opts = self.get_opts(m)
            self.assert_equals(len(opts), n, explain)
            # check that all are of the same type
            self.assert_equals(len(set(type(o) for o in opts)), 1, explain)
            # check that all have the same value
            self.assert_equals(len(set(a.value for o in opts for a in o.args)),
                               1, explain)
            # verify last one (others are identical)
            self.check_laa_o(opts[-1], ChAck, DRAck, TXPowAck, explain)

        async def ncr_optdr(m: lm.Msg, freq: int) -> lm.Msg:
            self.lw_dnlink(m,
                           port=0,
                           payload=lo.pack_opts([
                               lo.NewChannelReq(Chnl=3,
                                                Freq=freq // 100,
                                                MinDR=0,
                                                MaxDR=7)
                           ]))
            m = await self.lw_uplink()
            opts = self.get_opts(m)
            self.assert_equals(len(opts), 1)
            self.check_ncr_o(opts[0])
            return m

        m = await self.start_testmode()

        # a. ADR bit
        assert self.isadren(m)

        # b. TXPower
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(TXPow=7, DR=5, ChMaskCntl=6)]))
        m = await self.lw_uplink()
        check_laa(m)

        pstats = [0, 0]
        m = await self.ul_stats(m, 3, pstats=pstats)
        rssi0 = pstats[0] / pstats[1]

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(TXPow=0, DR=5, ChMaskCntl=6)]))
        m = await self.lw_uplink()
        check_laa(m)

        pstats = [0, 0]
        m = await self.ul_stats(m, 3, pstats=pstats)
        rssi1 = pstats[0] / pstats[1]

        print(f'RSSI @  2dBm: {rssi0:6.1f} dBm')
        print(f'RSSI @ 16dBm: {rssi1:6.1f} dBm')
        print(f'Difference:   {rssi1-rssi0:6.1f} dBm')
        self.assert_range(rssi0, -80, -10)
        self.assert_range(rssi1, -80, -10)
        self.assert_ge(rssi1 - rssi0, 6)

        # c. Required DataRates
        for dr in range(6):
            self.lw_dnlink(m,
                           port=0,
                           payload=lo.pack_opts(
                               [lo.LinkADRReq(TXPow=0, DR=dr, ChMaskCntl=6)]))
            m = await self.lw_uplink()
            check_laa(m)
            self.assert_equals(self.rps2dr(m['upmsg'].rps), dr)

        # d. Optional DataRates
        nchfreq = 869100000
        m = await ncr_optdr(m, nchfreq)
        for dr in range(6, 8):
            self.lw_dnlink(m,
                           port=0,
                           payload=lo.pack_opts(
                               [lo.LinkADRReq(TXPow=0, DR=dr, ChMaskCntl=6)]))
            m = await self.lw_uplink()
            check_laa(m)
            self.assert_equals(m['upmsg'].freq, nchfreq)
            self.assert_equals(self.rps2dr(m['upmsg'].rps), dr)
        m = await ncr_optdr(m, 0)
        self.assert_in(m['upmsg'].freq,
                       list(ch.freq for ch in self.region.upchannels))

        # e. ChannelMask
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([
                           lo.NewChannelReq(Chnl=3,
                                            Freq=nchfreq // 100,
                                            MinDR=0,
                                            MaxDR=5),
                           lo.LinkADRReq(TXPow=5, DR=5, ChMaskCntl=0, ChMask=7)
                       ]))

        m = await self.lw_uplink()
        opts = self.get_opts(m)
        self.assert_equals(len(opts), 2)
        self.check_ncr_o(opts[0])
        self.check_laa_o(opts[1])

        m = await self.check_freqs(
            m, frozenset(ch.freq for ch in self.region.upchannels))

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([
                           lo.LinkADRReq(TXPow=5,
                                         DR=5,
                                         ChMaskCntl=0,
                                         ChMask=0xf)
                       ]))

        m = await self.lw_uplink()
        opts = self.get_opts(m)
        self.assert_equals(len(opts), 1)
        self.check_laa_o(opts[0])

        m = await self.check_freqs(
            m,
            frozenset(
                it.chain([nchfreq],
                         (ch.freq for ch in self.region.upchannels))))

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([
                           lo.LinkADRReq(TXPow=5, DR=5, ChMaskCntl=0, ChMask=0)
                       ]))

        m = await self.lw_uplink()
        opts = self.get_opts(m)
        self.assert_equals(len(opts), 1)
        self.check_laa_o(opts[0], ChAck=0, DRAck=None, TXPowAck=None)

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([lo.NewChannelReq(Chnl=3,
                                                              Freq=0)]))

        m = await self.lw_uplink()
        opts = self.get_opts(m)
        self.assert_equals(len(opts), 1)
        self.check_ncr_o(opts[0])

        # f. Redundancy
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(DR=5, ChMaskCntl=6, NbTrans=2)]))
        m = await self.lw_uplink()
        check_laa(m)

        l = [await self.lw_uplink() for _ in range(3)]

        self.assert_equals(l[0]['MIC'], m['MIC'])
        self.assert_equals(l[2]['MIC'], l[1]['MIC'])

        m = l[-1]
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(DR=5, ChMaskCntl=6, NbTrans=1)]))
        m = await self.lw_uplink()
        check_laa(m)

        # g. ADRACKReq bit
        self.lw_dnlink(m)

        for i in range(64):
            m = await self.lw_uplink()
            self.assert_equals(self.isadrarq(m), False, explain=f'iter={i}')
            self.assert_equals(self.rps2dr(m['upmsg'].rps), 5)
        for dr in [5, 4, 3]:
            for i in range(32):
                m = await self.lw_uplink()
                self.assert_equals(self.isadrarq(m),
                                   True,
                                   explain=f'dr={dr}, iter={i}')
                self.assert_equals(self.rps2dr(m['upmsg'].rps), dr)

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(DR=5, ChMaskCntl=6)]))
        m = await self.lw_uplink()
        check_laa(m)
        self.assert_equals(self.rps2dr(m['upmsg'].rps), 5)

        # h. a.. Successful LinkADRReq commands block
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([
                           lo.LinkADRReq(ChMaskCntl=0, ChMask=0),
                           lo.LinkADRReq(TXPow=4,
                                         DR=4,
                                         ChMaskCntl=0,
                                         ChMask=3,
                                         NbTrans=1),
                           lo.LinkADRReq(TXPow=0,
                                         DR=3,
                                         ChMaskCntl=6,
                                         ChMask=0,
                                         NbTrans=1)
                       ]))

        m = await self.lw_uplink()
        check_laa_block(m, 3)

        m = await self.check_freqs(
            m, frozenset(ch.freq for ch in self.region.upchannels))

        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts(
                           [lo.LinkADRReq(DR=5, ChMaskCntl=6)]))
        m = await self.lw_uplink()
        check_laa(m)
        self.assert_equals(self.rps2dr(m['upmsg'].rps), 5)

        # h. b.. Unsuccessful LinkADRReq commands block
        self.lw_dnlink(m,
                       port=0,
                       payload=lo.pack_opts([
                           lo.LinkADRReq(ChMask=0x07, DR=4, TXPow=4),
                           lo.LinkADRReq(ChMaskCntl=0, ChMask=0)
                       ]))

        m = await self.lw_uplink()
        check_laa_block(m, 2, ChAck=0, DRAck=None, TXPowAck=None)

        self.assert_equals(self.rps2dr(m['upmsg'].rps), 5)

        self.lw_dnlink(m)  # empty downlink to avoid timeout (?)
        m = await self.check_freqs(
            m, frozenset(ch.freq for ch in self.region.upchannels))

        return True
Esempio n. 6
0
async def _(dut=createtest):
    m = await dut.start_testmode()

    def check_laa(m:LoraWanMsg, msg:str) -> None:
        opts = m.unpack_opts()
        assert len(opts) == 1, msg
        opt, = opts
        dut.check_laa_o(opt, explain=msg)

    def check_laa_block(m:LoraWanMsg, n:int, *, ChAck:Optional[int]=1, DRAck:Optional[int]=1, TXPowAck:Optional[int]=1, msg:str) -> None:
        opts = m.unpack_opts()
        assert len(opts) == n, msg
        # check that all have the correct type
        assert [type(o) for o in opts] == [lo.LinkADRAns for _ in range(n)], msg
        # check that all have the same value
        opt = opts[-1]
        assert list(opts) == [opt for _ in range(n)], msg
        # verify last one (others are identical)
        dut.check_laa_o(opt, ChAck, DRAck, TXPowAck, explain=msg)

    async def ncr_optdr(m:LoraWanMsg, freq:int, msg:str) -> LoraWanMsg:
        dut.dndf(m, 0, lo.pack_opts([lo.NewChannelReq(Chnl=3, Freq=freq//100, MinDR=0, MaxDR=7)]))
        m = await dut.updf(explain=msg)
        opts = m.unpack_opts()
        assert len(opts) == 1, msg
        opt, = opts
        dut.check_ncr_o(opt, explain=msg)
        return m

    # a. ADR bit
    assert m.isadren()

    # b. TXPower
    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=7, DR=5, ChMaskCntl=6)]))
    m = await dut.updf()
    check_laa(m, 'txpower=7')

    pstats = PowerStats()
    m = await dut.upstats(m, 3, pstats=pstats)
    rssi0 = pstats.avg()

    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=0, DR=5, ChMaskCntl=6)]))
    m = await dut.updf()
    check_laa(m, 'txpower=0')

    pstats.reset()
    m = await dut.upstats(m, 3, pstats=pstats)
    rssi1 = pstats.avg()

    print(f'RSSI @  2dBm: {rssi0:6.1f} dBm')
    print(f'RSSI @ 16dBm: {rssi1:6.1f} dBm')
    print(f'Difference:   {rssi1-rssi0:6.1f} dBm')
    assert rssi0 > -80 and rssi0 < -10
    assert rssi1 > -80 and rssi1 < -10
    assert (rssi1 - rssi0) >= 6

    # c. Required DataRates
    for dr in range(6):
        dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=0, DR=dr, ChMaskCntl=6)]))
        m = await dut.updf()
        check_laa(m, f'dr={dr}')
        assert m.dr == dr

    # d. Optional DataRates
    nchannel = ld.ChDef(freq=869100000, minDR=0, maxDR=7)
    reg = ld.Region_EU868()
    reg.upchannels.append(nchannel)
    dut.gateway.regions.append(reg)

    m = await ncr_optdr(m, nchannel.freq, 'create new channel')
    for dr in range(6, 8):
        dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=0, DR=dr, ChMaskCntl=6)]))
        m = await dut.updf()
        check_laa(m, f'dr={dr}')
        assert m.msg.freq == nchannel.freq, f'dr={dr}'
        assert m.dr == dr, f'dr={dr}'
    m = await ncr_optdr(m, 0, 'delete new channel')
    assert m.msg.freq in list(ch.freq for ch in dut.session['region'].upchannels)

    # e. ChannelMask
    dut.dndf(m, 0, lo.pack_opts([lo.NewChannelReq(Chnl=3, Freq=nchannel.freq//100, MinDR=0, MaxDR=5),
        lo.LinkADRReq(TXPow=5, DR=5, ChMaskCntl=0, ChMask=7)]))

    m = await dut.updf()
    opts = m.unpack_opts()
    assert len(opts) == 2
    opt1, opt2 = opts
    dut.check_ncr_o(opt1)
    dut.check_laa_o(opt2)

    m = await dut.check_freqs(m, frozenset(ch.freq for ch in dut.session['region'].upchannels))

    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=5, DR=5, ChMaskCntl=0, ChMask=0xf)]))

    m = await dut.updf()
    check_laa(m, 'chmask=0xf')

    m = await dut.check_freqs(m, frozenset(ch.freq for ch in reg.upchannels))

    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(TXPow=5, DR=5, ChMaskCntl=0, ChMask=0)]))

    m = await dut.updf()
    opts = m.unpack_opts()
    assert len(opts) == 1
    opt, = opts
    dut.check_laa_o(opt, ChAck=0, DRAck=None, TXPowAck=None)

    dut.dndf(m, 0, lo.pack_opts([lo.NewChannelReq(Chnl=3, Freq=0)]))

    m = await dut.updf()
    opts = m.unpack_opts()
    assert len(opts) == 1
    opt, = opts
    dut.check_ncr_o(opt)

    # f. Redundancy
    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(DR=5, ChMaskCntl=6, NbTrans=2)]))
    m = await dut.updf()
    check_laa(m, 'nbtrans=2')

    l = [await dut.updf() for _ in range(3)]

    assert l[0].rtm['MIC'] == m.rtm['MIC']
    assert l[2].rtm['MIC'] == l[1].rtm['MIC']

    m = l[-1]
    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(DR=5, ChMaskCntl=6, NbTrans=1)]))
    m = await dut.updf()
    check_laa(m, 'nbtrans=1')

    # g. ADRACKReq bit
    dut.dndf(m)

    for i in range(64):
        m = await dut.updf()
        assert m.isadrarq() == False, f'iter={i}'
        assert m.dr == 5, f'iter={i}'
    for dr in [5, 4, 3]:
        for i in range(32):
            m = await dut.updf()
            assert m.isadrarq() == True, f'dr={dr}, iter={i}'
            assert m.dr == dr, f'dr={dr}, iter={i}'

    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(DR=5, ChMaskCntl=6)]))
    m = await dut.updf()
    check_laa(m, 'dr=5')
    assert m.dr == 5

    # h. a.. Successful LinkADRReq commands block
    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(ChMaskCntl=0, ChMask=0),
        lo.LinkADRReq(TXPow=4, DR=4, ChMaskCntl=0, ChMask=3, NbTrans=1),
        lo.LinkADRReq(TXPow=0, DR=3, ChMaskCntl=6, ChMask=0, NbTrans=1)]))
    m = await dut.updf()
    check_laa_block(m, 3, msg='linkadrreq block')

    m = await dut.check_freqs(m, frozenset(ch.freq for ch in dut.session['region'].upchannels))

    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(DR=5, ChMaskCntl=6)]))
    m = await dut.updf()
    check_laa(m, 'dr=5')
    assert m.dr == 5

    # h. b.. Unsuccessful LinkADRReq commands block
    dut.dndf(m, 0, lo.pack_opts([lo.LinkADRReq(ChMask=0x07, DR=4, TXPow=4),
        lo.LinkADRReq(ChMaskCntl=0, ChMask=0)]))

    m = await dut.updf()
    check_laa_block(m, 2, ChAck=0, DRAck=None, TXPowAck=None, msg='invalid linkadrreq block')
    assert m.dr == 5

    dut.dndf(m) # empty downlink to avoid timeout (?)
    m = await dut.check_freqs(m, frozenset(ch.freq for ch in dut.session['region'].upchannels))