Coverage for tests/tests/test_parser_helpers.py: 0%

1#!/usr/bin/env python3

2"""RAMSES RF - Test the various helper APIs."""

3

4# TODO: add test for ramses_tx.frame.pkt_header()

5

6 from ramses_rf.system.zones import _transform

7 from ramses_tx.command import Command

8 from ramses_tx.exceptions import CommandInvalid, PacketInvalid

9 from ramses_tx.helpers import (

10 hex_from_bool,

11 hex_from_double,

12 hex_from_dtm,

13 hex_from_dts,

14 hex_from_flag8,

15 hex_from_percent,

16 # hex_from_str,

17 hex_from_temp,

18 hex_to_bool,

19 # hex_to_date,

20 hex_to_double,

21 hex_to_dtm,

22 hex_to_dts,

23 hex_to_flag8,

24 hex_to_percent,

25 # hex_to_str,

26 hex_to_temp,

27)

28 from ramses_tx.packet import Packet

29

30 from .helpers import TEST_DIR

31

32 WORK_DIR = f"{TEST_DIR}/parser_helpers"

33

34

35 def test_helper_demand_transform() -> None:

36 assert [x[1] for x in TRANSFORMS] == [_transform(x[0]) for x in TRANSFORMS]

37

38

39 def test_helper_field_parsers() -> None:

40 for val in ("FF", "00", "C8"):

41 assert val == hex_from_bool(hex_to_bool(val))

42

43 for val in ("7FFF", "0000", "0001", "0010", "0100", "1000"):

44 assert val == hex_from_double(hex_to_double(val))

45 assert val == hex_from_double(hex_to_double(val, factor=100), factor=100)

46

47 for val in (

48 "FF" * 6,

49 "FF" * 7,

50 "00141B0A07E3",

51 "00110E0507E5",

52 "0400041C0A07E3",

53 ):

54 assert val == hex_from_dtm(hex_to_dtm(val), incl_seconds=(len(val) == 14))

55

56 for val in ("00000000007F",):

57 assert val == hex_from_dts(hex_to_dts(val))

58

59 for val in ("00", "01", "08", "10", "E0", "CC", "FF"):

60 assert val == hex_from_flag8(hex_to_flag8(val))

61 assert val == hex_from_flag8(hex_to_flag8(val, lsb=True), lsb=True)

62

63 for val in ("7FFF", "7EFF", "0000", "0010", "0200", "D000"):

64 assert val == hex_from_temp(hex_to_temp(val))

65

66 for tmp in (None, False, -127.99, -100, -22.5, -1.53, 0, 1.53, 22.5, 100, 127.98):

67 assert tmp == hex_to_temp(hex_from_temp(tmp))

68

69 for cent in (None, 0, 0.05, 0.1, 0.5, 0.95, 1.0):

70 assert cent == hex_to_percent(hex_from_percent(cent))

71

72

73 def _test_pkt_dev_class() -> None:

74 """Check that the device class is correctly inferred from the packet.

75

76 Some packets (not all) can be used to determine the domain (Heat vs HVAC) and

77 class (e.g. BDR, CTL, FAN, etc)of the source device.

78 """

79

80 def proc_log_line(log_line: str) -> None:

81 if "#" not in log_line:

82 return

83 pkt_line, pkt_eval = log_line.split("#", maxsplit=1)

84

85 if not pkt_line[27:].strip():

86 return

87

88 pkt = Packet.from_file(pkt_line[:26], pkt_line[27:])

89

90 assert pkt.src.type == eval(pkt_eval) # TODO: finish this test

91

92 with open(f"{WORK_DIR}/pkt_dev_class.log") as f:

93 while line := (f.readline()):

94 if line.strip():

95 proc_log_line(line)

96

97

98 def test_pkt_addr_sets() -> None:

99 """Check that the address set is correctly inferred from the packet."""

100

101 def proc_log_line(log_line: str) -> None:

102 if "#" not in log_line:

103 return

104 pkt_line, pkt_eval = log_line.split("#", maxsplit=1)

105

106 if not pkt_line[27:].strip():

107 return

108 expected = eval(pkt_eval)

109

110 try:

111 cmd = Command(pkt_line[31:].rstrip())

112 cmd._validate(strict_checking=True)

113 except (CommandInvalid, PacketInvalid) as err:

114 assert err.__class__ == expected.__class__

115 assert err.message and err.message.startswith(expected.message)

116 return

117

118 res = {"src": cmd.src.id, "dst": cmd.dst.id, "set": [a.id for a in cmd._addrs]}

119 assert res == expected

120

121 with open(f"{WORK_DIR}/pkt_addr_set.log") as f:

122 while line := (f.readline()):

123 if (line := line.strip()) and line[:1] != "#":

124 proc_log_line(line)

125

126

127 TRANSFORMS = [

128 (0.000, 0),

129 (0.220, 0),

130 (0.230, 0),

131 (0.260, 0),

132 # (0.295, 0), # needs confirming

133 (0.300, 0),

134 # (0.305, 0), # needs confirming

135 (0.310, 0.01),

136 (0.340, 0.03),

137 (0.350, 0.04),

138 (0.370, 0.05),

139 (0.380, 0.06),

140 (0.390, 0.07),

141 (0.400, 0.08),

142 (0.410, 0.08),

143 (0.420, 0.09),

144 (0.430, 0.10),

145 (0.450, 0.11),

146 (0.470, 0.13),

147 (0.480, 0.14),

148 (0.530, 0.17),

149 (0.540, 0.18),

150 (0.550, 0.19),

151 (0.560, 0.20),

152 (0.575, 0.21),

153 (0.610, 0.23),

154 (0.620, 0.24),

155 (0.650, 0.26),

156 (0.660, 0.27),

157 (0.680, 0.29),

158 (0.690, 0.29),

159 # (0.695, 0.30), # needs confirming

160 (0.700, 0.30),

161 # (0.705, 0.31), # needs confirming

162 (0.720, 0.35),

163 (0.740, 0.39),

164 (0.760, 0.44),

165 (0.770, 0.46),

166 (0.790, 0.51),

167 (0.800, 0.53),

168 (0.820, 0.58),

169 (0.830, 0.60),

170 (0.840, 0.63),

171 (0.930, 0.84),

172 (0.950, 0.88),

173 # (0.995, 0.99), # needs confirming

174 (1.000, 1.0),

175]