Coverage for d7a/d7anp/addressee.py: 97%
64 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-24 08:03 +0200
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-24 08:03 +0200
1#
2# Copyright (c) 2015-2021 University of Antwerp, Aloxy NV.
3#
4# This file is part of pyd7a.
5# See https://github.com/Sub-IoT/pyd7a for further info.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
20# author: Christophe VG <contact@christophe.vg>
21# class implementation of addressee parameters
24import struct
25from enum import Enum
27from d7a.support.schema import Validatable, Types
28from d7a.types.ct import CT
31class IdType(Enum):
32 NBID = 0
33 NOID = 1
34 UID = 2
35 VID = 3
37class NlsMethod(Enum):
38 NONE = 0
39 AES_CTR = 1
40 AES_CBC_MAC_128 = 2
41 AES_CBC_MAC_64 = 3
42 AES_CBC_MAC_32 = 4
43 AES_CCM_128 = 5
44 AES_CCM_64 = 6
45 AES_CCM_32 = 7
47class Addressee(Validatable):
49 # addressee ID length
50 ID_LENGTH_NBID = 1
51 ID_LENGTH_NOID = 0
52 ID_LENGTH_VID = 2
53 ID_LENGTH_UID = 8
55 SCHEMA = [
56 {
57 # void identifier with reached devices estimation
58 "id_type" : Types.ENUM(IdType, allowedvalues=[IdType.NBID]),
59 "nls_method": Types.ENUM(NlsMethod),
60 "access_class": Types.BYTE(),
61 "id" : Types.OBJECT(CT)
62 },
63 {
64 # void identifier without reached devices estimation
65 "id_type": Types.ENUM(IdType, allowedvalues=[IdType.NOID]),
66 "nls_method": Types.ENUM(NlsMethod),
67 "access_class": Types.BYTE(),
68 "id": Types.INTEGER([None])
69 },
70 {
71 # virtual
72 "id_type" : Types.ENUM(IdType, allowedvalues=[IdType.VID]),
73 "nls_method": Types.ENUM(NlsMethod),
74 "access_class": Types.BYTE(),
75 "id" : Types.INTEGER(min=0, max=0xFFFF)
76 },
77 {
78 # unicast
79 "id_type" : Types.ENUM(IdType, allowedvalues=[IdType.UID]),
80 "nls_method": Types.ENUM(NlsMethod),
81 "access_class": Types.BYTE(),
82 "id" : Types.INTEGER(min=0, max=0xFFFFFFFFFFFFFFFF)
83 }
84 ]
87# SCHEMA = [
88# {
89# "id_type" : Types.INTEGER(IdType.ALL),
90# "cl" : Types.BITS(4),
91# "id_length" : Types.INTEGER([0, 2, 8]),
92# "id" : Types.INTEGER(min=0, max=0xFFFFFFFFFFFFFFFF)
93# }
94# ]
96 def __init__(self, access_class=0, id_type=IdType.NOID, id=None, nls_method=NlsMethod.NONE):
97 self.id_type = id_type
98 self.access_class = access_class
99 self.id = id
100 self.nls_method = nls_method
101 super(Addressee, self).__init__()
103 @property
104 def id_length(self):
105 return Addressee.length_for(id_type=self.id_type)
107 @classmethod
108 def length_for(self, id_type):
109 if id_type == IdType.NBID: return Addressee.ID_LENGTH_NBID
110 if id_type == IdType.NOID: return Addressee.ID_LENGTH_NOID
111 if id_type == IdType.VID: return Addressee.ID_LENGTH_VID
112 if id_type == IdType.UID: return Addressee.ID_LENGTH_UID
114 @staticmethod
115 def parse(s):
116 _ = s.read("pad:2")
117 id_type = IdType(s.read("uint:2"))
118 nls_method = NlsMethod(s.read("uint:4"))
119 cl = s.read("uint:8")
120 l = Addressee.length_for(id_type)
121 id = s.read("uint:"+str(l*8)) if l > 0 else None
122 if id_type == IdType.NBID:
123 id = CT().compress(value=id)
125 return Addressee(id_type=id_type, access_class=cl, id=id, nls_method=nls_method)
127 def __iter__(self):
128 byte = 0
129 # pad 2 << 7 << 6
130 byte |= self.id_type.value << 4
131 byte += self.nls_method.value
132 yield byte
133 yield self.access_class
134 if self.id_length > 0:
135 id_value = self.id
136 if self.id_type == IdType.NBID:
137 # self.id is a CT
138 id_value = self.id.compressed_value()
140 id = bytearray(struct.pack(">Q", id_value))[8-self.id_length:]
141 for byte in id: yield byte
143 def __str__(self):
144 return "ac={}, id_type={}, id={}".format(self.access_class, self.id_type, self.id)