@switchbot/homebridge-switchbot 4.3.2-beta.9 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/.github/copilot-instructions.md +328 -0
  2. package/.github/scripts/npm-version-script-esm-auto.js +207 -0
  3. package/.github/workflows/beta-release.yml +8 -12
  4. package/.github/workflows/release.yml +54 -22
  5. package/CHANGELOG.md +1 -1
  6. package/README.md +13 -10
  7. package/config.schema.json +2 -2
  8. package/coverage/base.css +224 -0
  9. package/coverage/block-navigation.js +87 -0
  10. package/coverage/clover.xml +15847 -0
  11. package/coverage/coverage-final.json +42 -0
  12. package/coverage/docs/assets/dmt/dmt-component-data.js.html +85 -0
  13. package/coverage/docs/assets/dmt/dmt-components.js.html +286 -0
  14. package/coverage/docs/assets/dmt/index.html +131 -0
  15. package/coverage/docs/assets/hierarchy.js.html +85 -0
  16. package/coverage/docs/assets/icons.js.html +136 -0
  17. package/coverage/docs/assets/index.html +146 -0
  18. package/coverage/docs/assets/main.js.html +265 -0
  19. package/coverage/favicon.png +0 -0
  20. package/coverage/index.html +191 -0
  21. package/coverage/prettify.css +1 -0
  22. package/coverage/prettify.js +2 -0
  23. package/coverage/sort-arrow-sprite.png +0 -0
  24. package/coverage/sorter.js +196 -0
  25. package/coverage/src/device/blindtilt.ts.html +3238 -0
  26. package/coverage/src/device/bot.ts.html +2803 -0
  27. package/coverage/src/device/ceilinglight.ts.html +2338 -0
  28. package/coverage/src/device/colorbulb.ts.html +2824 -0
  29. package/coverage/src/device/contact.ts.html +1465 -0
  30. package/coverage/src/device/curtain.ts.html +2869 -0
  31. package/coverage/src/device/device.ts.html +2500 -0
  32. package/coverage/src/device/fan.ts.html +2242 -0
  33. package/coverage/src/device/hub.ts.html +1408 -0
  34. package/coverage/src/device/humidifier.ts.html +2116 -0
  35. package/coverage/src/device/index.html +416 -0
  36. package/coverage/src/device/iosensor.ts.html +1375 -0
  37. package/coverage/src/device/lightstrip.ts.html +2617 -0
  38. package/coverage/src/device/lock.ts.html +1963 -0
  39. package/coverage/src/device/meter.ts.html +1372 -0
  40. package/coverage/src/device/meterplus.ts.html +1384 -0
  41. package/coverage/src/device/meterpro.ts.html +1618 -0
  42. package/coverage/src/device/motion.ts.html +1264 -0
  43. package/coverage/src/device/plug.ts.html +1372 -0
  44. package/coverage/src/device/relayswitch.ts.html +2284 -0
  45. package/coverage/src/device/robotvacuumcleaner.ts.html +1810 -0
  46. package/coverage/src/device/waterdetector.ts.html +1294 -0
  47. package/coverage/src/homebridge-ui/index.html +116 -0
  48. package/coverage/src/homebridge-ui/server.ts.html +229 -0
  49. package/coverage/src/index.html +161 -0
  50. package/coverage/src/index.ts.html +124 -0
  51. package/coverage/src/irdevice/airconditioner.ts.html +1687 -0
  52. package/coverage/src/irdevice/airpurifier.ts.html +844 -0
  53. package/coverage/src/irdevice/camera.ts.html +475 -0
  54. package/coverage/src/irdevice/fan.ts.html +766 -0
  55. package/coverage/src/irdevice/index.html +251 -0
  56. package/coverage/src/irdevice/irdevice.ts.html +1117 -0
  57. package/coverage/src/irdevice/light.ts.html +826 -0
  58. package/coverage/src/irdevice/other.ts.html +2458 -0
  59. package/coverage/src/irdevice/tv.ts.html +1222 -0
  60. package/coverage/src/irdevice/vacuumcleaner.ts.html +466 -0
  61. package/coverage/src/irdevice/waterheater.ts.html +469 -0
  62. package/coverage/src/platform.ts.html +8776 -0
  63. package/coverage/src/settings.ts.html +934 -0
  64. package/coverage/src/utils.ts.html +2092 -0
  65. package/dist/device/blindtilt.d.ts.map +1 -1
  66. package/dist/device/blindtilt.js +12 -4
  67. package/dist/device/blindtilt.js.map +1 -1
  68. package/dist/device/bot.d.ts.map +1 -1
  69. package/dist/device/bot.js +12 -4
  70. package/dist/device/bot.js.map +1 -1
  71. package/dist/device/ceilinglight.d.ts.map +1 -1
  72. package/dist/device/ceilinglight.js +18 -7
  73. package/dist/device/ceilinglight.js.map +1 -1
  74. package/dist/device/colorbulb.d.ts.map +1 -1
  75. package/dist/device/colorbulb.js +18 -7
  76. package/dist/device/colorbulb.js.map +1 -1
  77. package/dist/device/contact.d.ts.map +1 -1
  78. package/dist/device/contact.js +6 -2
  79. package/dist/device/contact.js.map +1 -1
  80. package/dist/device/curtain.d.ts.map +1 -1
  81. package/dist/device/curtain.js +12 -4
  82. package/dist/device/curtain.js.map +1 -1
  83. package/dist/device/device.d.ts +5 -7
  84. package/dist/device/device.d.ts.map +1 -1
  85. package/dist/device/device.js +11 -5
  86. package/dist/device/device.js.map +1 -1
  87. package/dist/device/fan.d.ts.map +1 -1
  88. package/dist/device/fan.js +16 -6
  89. package/dist/device/fan.js.map +1 -1
  90. package/dist/device/hub.d.ts +2 -2
  91. package/dist/device/hub.d.ts.map +1 -1
  92. package/dist/device/hub.js +8 -3
  93. package/dist/device/hub.js.map +1 -1
  94. package/dist/device/humidifier.d.ts.map +1 -1
  95. package/dist/device/humidifier.js +16 -6
  96. package/dist/device/humidifier.js.map +1 -1
  97. package/dist/device/iosensor.d.ts.map +1 -1
  98. package/dist/device/iosensor.js +6 -2
  99. package/dist/device/iosensor.js.map +1 -1
  100. package/dist/device/lightstrip.d.ts.map +1 -1
  101. package/dist/device/lightstrip.js +16 -6
  102. package/dist/device/lightstrip.js.map +1 -1
  103. package/dist/device/lock.d.ts.map +1 -1
  104. package/dist/device/lock.js +12 -4
  105. package/dist/device/lock.js.map +1 -1
  106. package/dist/device/meter.d.ts.map +1 -1
  107. package/dist/device/meter.js +6 -2
  108. package/dist/device/meter.js.map +1 -1
  109. package/dist/device/meterplus.d.ts.map +1 -1
  110. package/dist/device/meterplus.js +6 -2
  111. package/dist/device/meterplus.js.map +1 -1
  112. package/dist/device/meterpro.d.ts.map +1 -1
  113. package/dist/device/meterpro.js +7 -4
  114. package/dist/device/meterpro.js.map +1 -1
  115. package/dist/device/motion.d.ts.map +1 -1
  116. package/dist/device/motion.js +6 -2
  117. package/dist/device/motion.js.map +1 -1
  118. package/dist/device/occupancy.d.ts +42 -0
  119. package/dist/device/occupancy.d.ts.map +1 -0
  120. package/dist/device/occupancy.js +349 -0
  121. package/dist/device/occupancy.js.map +1 -0
  122. package/dist/device/plug.d.ts.map +1 -1
  123. package/dist/device/plug.js +12 -4
  124. package/dist/device/plug.js.map +1 -1
  125. package/dist/device/relayswitch.d.ts.map +1 -1
  126. package/dist/device/relayswitch.js +12 -4
  127. package/dist/device/relayswitch.js.map +1 -1
  128. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  129. package/dist/device/robotvacuumcleaner.js +14 -5
  130. package/dist/device/robotvacuumcleaner.js.map +1 -1
  131. package/dist/device/waterdetector.d.ts.map +1 -1
  132. package/dist/device/waterdetector.js +6 -2
  133. package/dist/device/waterdetector.js.map +1 -1
  134. package/dist/homebridge-ui/public/index.html +1 -1
  135. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  136. package/dist/irdevice/airconditioner.js +2 -1
  137. package/dist/irdevice/airconditioner.js.map +1 -1
  138. package/dist/irdevice/airpurifier.d.ts +1 -1
  139. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  140. package/dist/irdevice/airpurifier.js +6 -5
  141. package/dist/irdevice/airpurifier.js.map +1 -1
  142. package/dist/irdevice/camera.d.ts.map +1 -1
  143. package/dist/irdevice/camera.js +2 -1
  144. package/dist/irdevice/camera.js.map +1 -1
  145. package/dist/irdevice/fan.d.ts.map +1 -1
  146. package/dist/irdevice/fan.js +2 -1
  147. package/dist/irdevice/fan.js.map +1 -1
  148. package/dist/irdevice/irdevice.d.ts +2 -6
  149. package/dist/irdevice/irdevice.d.ts.map +1 -1
  150. package/dist/irdevice/irdevice.js.map +1 -1
  151. package/dist/irdevice/light.d.ts.map +1 -1
  152. package/dist/irdevice/light.js +2 -1
  153. package/dist/irdevice/light.js.map +1 -1
  154. package/dist/irdevice/other.d.ts.map +1 -1
  155. package/dist/irdevice/other.js +2 -1
  156. package/dist/irdevice/other.js.map +1 -1
  157. package/dist/irdevice/tv.d.ts.map +1 -1
  158. package/dist/irdevice/tv.js +2 -1
  159. package/dist/irdevice/tv.js.map +1 -1
  160. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  161. package/dist/irdevice/vacuumcleaner.js +2 -1
  162. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  163. package/dist/irdevice/waterheater.d.ts.map +1 -1
  164. package/dist/irdevice/waterheater.js +2 -1
  165. package/dist/irdevice/waterheater.js.map +1 -1
  166. package/dist/platform.d.ts +2 -2
  167. package/dist/platform.d.ts.map +1 -1
  168. package/dist/platform.js +77 -78
  169. package/dist/platform.js.map +1 -1
  170. package/dist/settings.d.ts +6 -0
  171. package/dist/settings.d.ts.map +1 -1
  172. package/dist/settings.js +1 -0
  173. package/dist/settings.js.map +1 -1
  174. package/docs/index.html +20 -11
  175. package/docs/variables/default.html +1 -1
  176. package/eslint.config.js +0 -1
  177. package/package.json +9 -10
  178. package/src/device/blindtilt.ts +10 -4
  179. package/src/device/bot.ts +10 -4
  180. package/src/device/ceilinglight.ts +16 -7
  181. package/src/device/colorbulb.ts +16 -7
  182. package/src/device/contact.ts +5 -2
  183. package/src/device/curtain.ts +12 -6
  184. package/src/device/device.ts +14 -8
  185. package/src/device/fan.ts +14 -6
  186. package/src/device/hub.ts +10 -6
  187. package/src/device/humidifier.ts +14 -6
  188. package/src/device/iosensor.ts +5 -2
  189. package/src/device/lightstrip.ts +14 -6
  190. package/src/device/lock.ts +10 -4
  191. package/src/device/meter.ts +6 -3
  192. package/src/device/meterplus.ts +5 -2
  193. package/src/device/meterpro.ts +7 -5
  194. package/src/device/motion.ts +5 -2
  195. package/src/device/occupancy.ts +393 -0
  196. package/src/device/plug.ts +10 -4
  197. package/src/device/relayswitch.ts +10 -4
  198. package/src/device/robotvacuumcleaner.ts +12 -5
  199. package/src/device/waterdetector.ts +5 -2
  200. package/src/homebridge-ui/public/index.html +1 -1
  201. package/src/irdevice/airconditioner.ts +2 -1
  202. package/src/irdevice/airpurifier.ts +6 -5
  203. package/src/irdevice/camera.ts +2 -1
  204. package/src/irdevice/fan.ts +2 -1
  205. package/src/irdevice/irdevice.ts +2 -2
  206. package/src/irdevice/light.ts +2 -1
  207. package/src/irdevice/other.ts +2 -1
  208. package/src/irdevice/tv.ts +2 -1
  209. package/src/irdevice/vacuumcleaner.ts +2 -1
  210. package/src/irdevice/waterheater.ts +2 -1
  211. package/src/platform.ts +80 -88
  212. package/src/settings.ts +7 -0
  213. package/.github/npm-version-script-esm.js +0 -97
  214. package/.github/workflows/build.yml +0 -18
  215. package/.github/workflows/changerelease.yml +0 -11
  216. package/.github/workflows/labeler.yml +0 -16
  217. package/.github/workflows/release-drafter.yml +0 -14
  218. package/dist/device/airpurifier.d.ts +0 -54
  219. package/dist/device/airpurifier.d.ts.map +0 -1
  220. package/dist/device/airpurifier.js +0 -527
  221. package/dist/device/airpurifier.js.map +0 -1
  222. package/src/device/airpurifier.ts +0 -563
@@ -0,0 +1,1618 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/device/meterpro.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> / <a href="index.html">src/device</a> meterpro.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">1.57% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>6/380</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">0% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>0/1</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">0% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>0/1</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">1.57% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>6/380</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
578
+ <span class="cline-any cline-neutral">&nbsp;</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-neutral">&nbsp;</span>
581
+ <span class="cline-any cline-neutral">&nbsp;</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-neutral">&nbsp;</span>
584
+ <span class="cline-any cline-neutral">&nbsp;</span>
585
+ <span class="cline-any cline-neutral">&nbsp;</span>
586
+ <span class="cline-any cline-neutral">&nbsp;</span>
587
+ <span class="cline-any cline-yes">1x</span>
588
+ <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-neutral">&nbsp;</span>
590
+ <span class="cline-any cline-neutral">&nbsp;</span>
591
+ <span class="cline-any cline-neutral">&nbsp;</span>
592
+ <span class="cline-any cline-yes">1x</span>
593
+ <span class="cline-any cline-yes">1x</span>
594
+ <span class="cline-any cline-neutral">&nbsp;</span>
595
+ <span class="cline-any cline-yes">1x</span>
596
+ <span class="cline-any cline-yes">1x</span>
597
+ <span class="cline-any cline-neutral">&nbsp;</span>
598
+ <span class="cline-any cline-neutral">&nbsp;</span>
599
+ <span class="cline-any cline-neutral">&nbsp;</span>
600
+ <span class="cline-any cline-neutral">&nbsp;</span>
601
+ <span class="cline-any cline-neutral">&nbsp;</span>
602
+ <span class="cline-any cline-neutral">&nbsp;</span>
603
+ <span class="cline-any cline-yes">1x</span>
604
+ <span class="cline-any cline-neutral">&nbsp;</span>
605
+ <span class="cline-any cline-no">&nbsp;</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-neutral">&nbsp;</span>
609
+ <span class="cline-any cline-neutral">&nbsp;</span>
610
+ <span class="cline-any cline-neutral">&nbsp;</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-no">&nbsp;</span>
613
+ <span class="cline-any cline-neutral">&nbsp;</span>
614
+ <span class="cline-any cline-neutral">&nbsp;</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-no">&nbsp;</span>
619
+ <span class="cline-any cline-neutral">&nbsp;</span>
620
+ <span class="cline-any cline-neutral">&nbsp;</span>
621
+ <span class="cline-any cline-neutral">&nbsp;</span>
622
+ <span class="cline-any cline-neutral">&nbsp;</span>
623
+ <span class="cline-any cline-neutral">&nbsp;</span>
624
+ <span class="cline-any cline-no">&nbsp;</span>
625
+ <span class="cline-any cline-neutral">&nbsp;</span>
626
+ <span class="cline-any cline-neutral">&nbsp;</span>
627
+ <span class="cline-any cline-neutral">&nbsp;</span>
628
+ <span class="cline-any cline-neutral">&nbsp;</span>
629
+ <span class="cline-any cline-neutral">&nbsp;</span>
630
+ <span class="cline-any cline-neutral">&nbsp;</span>
631
+ <span class="cline-any cline-neutral">&nbsp;</span>
632
+ <span class="cline-any cline-no">&nbsp;</span>
633
+ <span class="cline-any cline-neutral">&nbsp;</span>
634
+ <span class="cline-any cline-neutral">&nbsp;</span>
635
+ <span class="cline-any cline-no">&nbsp;</span>
636
+ <span class="cline-any cline-neutral">&nbsp;</span>
637
+ <span class="cline-any cline-neutral">&nbsp;</span>
638
+ <span class="cline-any cline-no">&nbsp;</span>
639
+ <span class="cline-any cline-neutral">&nbsp;</span>
640
+ <span class="cline-any cline-neutral">&nbsp;</span>
641
+ <span class="cline-any cline-no">&nbsp;</span>
642
+ <span class="cline-any cline-no">&nbsp;</span>
643
+ <span class="cline-any cline-neutral">&nbsp;</span>
644
+ <span class="cline-any cline-no">&nbsp;</span>
645
+ <span class="cline-any cline-no">&nbsp;</span>
646
+ <span class="cline-any cline-no">&nbsp;</span>
647
+ <span class="cline-any cline-no">&nbsp;</span>
648
+ <span class="cline-any cline-no">&nbsp;</span>
649
+ <span class="cline-any cline-no">&nbsp;</span>
650
+ <span class="cline-any cline-neutral">&nbsp;</span>
651
+ <span class="cline-any cline-no">&nbsp;</span>
652
+ <span class="cline-any cline-neutral">&nbsp;</span>
653
+ <span class="cline-any cline-neutral">&nbsp;</span>
654
+ <span class="cline-any cline-no">&nbsp;</span>
655
+ <span class="cline-any cline-no">&nbsp;</span>
656
+ <span class="cline-any cline-neutral">&nbsp;</span>
657
+ <span class="cline-any cline-neutral">&nbsp;</span>
658
+ <span class="cline-any cline-no">&nbsp;</span>
659
+ <span class="cline-any cline-no">&nbsp;</span>
660
+ <span class="cline-any cline-no">&nbsp;</span>
661
+ <span class="cline-any cline-no">&nbsp;</span>
662
+ <span class="cline-any cline-no">&nbsp;</span>
663
+ <span class="cline-any cline-no">&nbsp;</span>
664
+ <span class="cline-any cline-no">&nbsp;</span>
665
+ <span class="cline-any cline-no">&nbsp;</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-neutral">&nbsp;</span>
668
+ <span class="cline-any cline-no">&nbsp;</span>
669
+ <span class="cline-any cline-no">&nbsp;</span>
670
+ <span class="cline-any cline-no">&nbsp;</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-no">&nbsp;</span>
673
+ <span class="cline-any cline-no">&nbsp;</span>
674
+ <span class="cline-any cline-no">&nbsp;</span>
675
+ <span class="cline-any cline-neutral">&nbsp;</span>
676
+ <span class="cline-any cline-neutral">&nbsp;</span>
677
+ <span class="cline-any cline-no">&nbsp;</span>
678
+ <span class="cline-any cline-no">&nbsp;</span>
679
+ <span class="cline-any cline-no">&nbsp;</span>
680
+ <span class="cline-any cline-no">&nbsp;</span>
681
+ <span class="cline-any cline-no">&nbsp;</span>
682
+ <span class="cline-any cline-no">&nbsp;</span>
683
+ <span class="cline-any cline-no">&nbsp;</span>
684
+ <span class="cline-any cline-no">&nbsp;</span>
685
+ <span class="cline-any cline-no">&nbsp;</span>
686
+ <span class="cline-any cline-no">&nbsp;</span>
687
+ <span class="cline-any cline-no">&nbsp;</span>
688
+ <span class="cline-any cline-no">&nbsp;</span>
689
+ <span class="cline-any cline-no">&nbsp;</span>
690
+ <span class="cline-any cline-no">&nbsp;</span>
691
+ <span class="cline-any cline-neutral">&nbsp;</span>
692
+ <span class="cline-any cline-neutral">&nbsp;</span>
693
+ <span class="cline-any cline-no">&nbsp;</span>
694
+ <span class="cline-any cline-no">&nbsp;</span>
695
+ <span class="cline-any cline-no">&nbsp;</span>
696
+ <span class="cline-any cline-no">&nbsp;</span>
697
+ <span class="cline-any cline-no">&nbsp;</span>
698
+ <span class="cline-any cline-no">&nbsp;</span>
699
+ <span class="cline-any cline-no">&nbsp;</span>
700
+ <span class="cline-any cline-no">&nbsp;</span>
701
+ <span class="cline-any cline-no">&nbsp;</span>
702
+ <span class="cline-any cline-no">&nbsp;</span>
703
+ <span class="cline-any cline-neutral">&nbsp;</span>
704
+ <span class="cline-any cline-no">&nbsp;</span>
705
+ <span class="cline-any cline-no">&nbsp;</span>
706
+ <span class="cline-any cline-no">&nbsp;</span>
707
+ <span class="cline-any cline-no">&nbsp;</span>
708
+ <span class="cline-any cline-no">&nbsp;</span>
709
+ <span class="cline-any cline-no">&nbsp;</span>
710
+ <span class="cline-any cline-no">&nbsp;</span>
711
+ <span class="cline-any cline-no">&nbsp;</span>
712
+ <span class="cline-any cline-no">&nbsp;</span>
713
+ <span class="cline-any cline-no">&nbsp;</span>
714
+ <span class="cline-any cline-no">&nbsp;</span>
715
+ <span class="cline-any cline-no">&nbsp;</span>
716
+ <span class="cline-any cline-no">&nbsp;</span>
717
+ <span class="cline-any cline-no">&nbsp;</span>
718
+ <span class="cline-any cline-neutral">&nbsp;</span>
719
+ <span class="cline-any cline-neutral">&nbsp;</span>
720
+ <span class="cline-any cline-no">&nbsp;</span>
721
+ <span class="cline-any cline-no">&nbsp;</span>
722
+ <span class="cline-any cline-no">&nbsp;</span>
723
+ <span class="cline-any cline-no">&nbsp;</span>
724
+ <span class="cline-any cline-no">&nbsp;</span>
725
+ <span class="cline-any cline-no">&nbsp;</span>
726
+ <span class="cline-any cline-neutral">&nbsp;</span>
727
+ <span class="cline-any cline-neutral">&nbsp;</span>
728
+ <span class="cline-any cline-no">&nbsp;</span>
729
+ <span class="cline-any cline-no">&nbsp;</span>
730
+ <span class="cline-any cline-no">&nbsp;</span>
731
+ <span class="cline-any cline-no">&nbsp;</span>
732
+ <span class="cline-any cline-no">&nbsp;</span>
733
+ <span class="cline-any cline-no">&nbsp;</span>
734
+ <span class="cline-any cline-no">&nbsp;</span>
735
+ <span class="cline-any cline-no">&nbsp;</span>
736
+ <span class="cline-any cline-no">&nbsp;</span>
737
+ <span class="cline-any cline-no">&nbsp;</span>
738
+ <span class="cline-any cline-no">&nbsp;</span>
739
+ <span class="cline-any cline-no">&nbsp;</span>
740
+ <span class="cline-any cline-no">&nbsp;</span>
741
+ <span class="cline-any cline-no">&nbsp;</span>
742
+ <span class="cline-any cline-no">&nbsp;</span>
743
+ <span class="cline-any cline-neutral">&nbsp;</span>
744
+ <span class="cline-any cline-neutral">&nbsp;</span>
745
+ <span class="cline-any cline-no">&nbsp;</span>
746
+ <span class="cline-any cline-no">&nbsp;</span>
747
+ <span class="cline-any cline-no">&nbsp;</span>
748
+ <span class="cline-any cline-no">&nbsp;</span>
749
+ <span class="cline-any cline-no">&nbsp;</span>
750
+ <span class="cline-any cline-no">&nbsp;</span>
751
+ <span class="cline-any cline-no">&nbsp;</span>
752
+ <span class="cline-any cline-no">&nbsp;</span>
753
+ <span class="cline-any cline-no">&nbsp;</span>
754
+ <span class="cline-any cline-no">&nbsp;</span>
755
+ <span class="cline-any cline-no">&nbsp;</span>
756
+ <span class="cline-any cline-no">&nbsp;</span>
757
+ <span class="cline-any cline-no">&nbsp;</span>
758
+ <span class="cline-any cline-no">&nbsp;</span>
759
+ <span class="cline-any cline-no">&nbsp;</span>
760
+ <span class="cline-any cline-neutral">&nbsp;</span>
761
+ <span class="cline-any cline-neutral">&nbsp;</span>
762
+ <span class="cline-any cline-no">&nbsp;</span>
763
+ <span class="cline-any cline-no">&nbsp;</span>
764
+ <span class="cline-any cline-no">&nbsp;</span>
765
+ <span class="cline-any cline-no">&nbsp;</span>
766
+ <span class="cline-any cline-no">&nbsp;</span>
767
+ <span class="cline-any cline-no">&nbsp;</span>
768
+ <span class="cline-any cline-neutral">&nbsp;</span>
769
+ <span class="cline-any cline-neutral">&nbsp;</span>
770
+ <span class="cline-any cline-no">&nbsp;</span>
771
+ <span class="cline-any cline-no">&nbsp;</span>
772
+ <span class="cline-any cline-no">&nbsp;</span>
773
+ <span class="cline-any cline-no">&nbsp;</span>
774
+ <span class="cline-any cline-no">&nbsp;</span>
775
+ <span class="cline-any cline-no">&nbsp;</span>
776
+ <span class="cline-any cline-neutral">&nbsp;</span>
777
+ <span class="cline-any cline-neutral">&nbsp;</span>
778
+ <span class="cline-any cline-no">&nbsp;</span>
779
+ <span class="cline-any cline-no">&nbsp;</span>
780
+ <span class="cline-any cline-no">&nbsp;</span>
781
+ <span class="cline-any cline-no">&nbsp;</span>
782
+ <span class="cline-any cline-no">&nbsp;</span>
783
+ <span class="cline-any cline-no">&nbsp;</span>
784
+ <span class="cline-any cline-neutral">&nbsp;</span>
785
+ <span class="cline-any cline-neutral">&nbsp;</span>
786
+ <span class="cline-any cline-no">&nbsp;</span>
787
+ <span class="cline-any cline-no">&nbsp;</span>
788
+ <span class="cline-any cline-no">&nbsp;</span>
789
+ <span class="cline-any cline-no">&nbsp;</span>
790
+ <span class="cline-any cline-no">&nbsp;</span>
791
+ <span class="cline-any cline-no">&nbsp;</span>
792
+ <span class="cline-any cline-neutral">&nbsp;</span>
793
+ <span class="cline-any cline-no">&nbsp;</span>
794
+ <span class="cline-any cline-no">&nbsp;</span>
795
+ <span class="cline-any cline-no">&nbsp;</span>
796
+ <span class="cline-any cline-neutral">&nbsp;</span>
797
+ <span class="cline-any cline-neutral">&nbsp;</span>
798
+ <span class="cline-any cline-no">&nbsp;</span>
799
+ <span class="cline-any cline-no">&nbsp;</span>
800
+ <span class="cline-any cline-no">&nbsp;</span>
801
+ <span class="cline-any cline-no">&nbsp;</span>
802
+ <span class="cline-any cline-neutral">&nbsp;</span>
803
+ <span class="cline-any cline-no">&nbsp;</span>
804
+ <span class="cline-any cline-no">&nbsp;</span>
805
+ <span class="cline-any cline-no">&nbsp;</span>
806
+ <span class="cline-any cline-no">&nbsp;</span>
807
+ <span class="cline-any cline-no">&nbsp;</span>
808
+ <span class="cline-any cline-neutral">&nbsp;</span>
809
+ <span class="cline-any cline-no">&nbsp;</span>
810
+ <span class="cline-any cline-no">&nbsp;</span>
811
+ <span class="cline-any cline-no">&nbsp;</span>
812
+ <span class="cline-any cline-no">&nbsp;</span>
813
+ <span class="cline-any cline-no">&nbsp;</span>
814
+ <span class="cline-any cline-no">&nbsp;</span>
815
+ <span class="cline-any cline-no">&nbsp;</span>
816
+ <span class="cline-any cline-no">&nbsp;</span>
817
+ <span class="cline-any cline-no">&nbsp;</span>
818
+ <span class="cline-any cline-neutral">&nbsp;</span>
819
+ <span class="cline-any cline-no">&nbsp;</span>
820
+ <span class="cline-any cline-neutral">&nbsp;</span>
821
+ <span class="cline-any cline-no">&nbsp;</span>
822
+ <span class="cline-any cline-no">&nbsp;</span>
823
+ <span class="cline-any cline-neutral">&nbsp;</span>
824
+ <span class="cline-any cline-no">&nbsp;</span>
825
+ <span class="cline-any cline-no">&nbsp;</span>
826
+ <span class="cline-any cline-no">&nbsp;</span>
827
+ <span class="cline-any cline-no">&nbsp;</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-no">&nbsp;</span>
830
+ <span class="cline-any cline-neutral">&nbsp;</span>
831
+ <span class="cline-any cline-no">&nbsp;</span>
832
+ <span class="cline-any cline-no">&nbsp;</span>
833
+ <span class="cline-any cline-no">&nbsp;</span>
834
+ <span class="cline-any cline-neutral">&nbsp;</span>
835
+ <span class="cline-any cline-neutral">&nbsp;</span>
836
+ <span class="cline-any cline-no">&nbsp;</span>
837
+ <span class="cline-any cline-no">&nbsp;</span>
838
+ <span class="cline-any cline-no">&nbsp;</span>
839
+ <span class="cline-any cline-no">&nbsp;</span>
840
+ <span class="cline-any cline-neutral">&nbsp;</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-no">&nbsp;</span>
843
+ <span class="cline-any cline-no">&nbsp;</span>
844
+ <span class="cline-any cline-no">&nbsp;</span>
845
+ <span class="cline-any cline-no">&nbsp;</span>
846
+ <span class="cline-any cline-neutral">&nbsp;</span>
847
+ <span class="cline-any cline-neutral">&nbsp;</span>
848
+ <span class="cline-any cline-no">&nbsp;</span>
849
+ <span class="cline-any cline-no">&nbsp;</span>
850
+ <span class="cline-any cline-no">&nbsp;</span>
851
+ <span class="cline-any cline-no">&nbsp;</span>
852
+ <span class="cline-any cline-no">&nbsp;</span>
853
+ <span class="cline-any cline-no">&nbsp;</span>
854
+ <span class="cline-any cline-no">&nbsp;</span>
855
+ <span class="cline-any cline-no">&nbsp;</span>
856
+ <span class="cline-any cline-no">&nbsp;</span>
857
+ <span class="cline-any cline-no">&nbsp;</span>
858
+ <span class="cline-any cline-neutral">&nbsp;</span>
859
+ <span class="cline-any cline-neutral">&nbsp;</span>
860
+ <span class="cline-any cline-no">&nbsp;</span>
861
+ <span class="cline-any cline-neutral">&nbsp;</span>
862
+ <span class="cline-any cline-no">&nbsp;</span>
863
+ <span class="cline-any cline-no">&nbsp;</span>
864
+ <span class="cline-any cline-neutral">&nbsp;</span>
865
+ <span class="cline-any cline-neutral">&nbsp;</span>
866
+ <span class="cline-any cline-no">&nbsp;</span>
867
+ <span class="cline-any cline-no">&nbsp;</span>
868
+ <span class="cline-any cline-no">&nbsp;</span>
869
+ <span class="cline-any cline-no">&nbsp;</span>
870
+ <span class="cline-any cline-no">&nbsp;</span>
871
+ <span class="cline-any cline-neutral">&nbsp;</span>
872
+ <span class="cline-any cline-neutral">&nbsp;</span>
873
+ <span class="cline-any cline-no">&nbsp;</span>
874
+ <span class="cline-any cline-no">&nbsp;</span>
875
+ <span class="cline-any cline-no">&nbsp;</span>
876
+ <span class="cline-any cline-no">&nbsp;</span>
877
+ <span class="cline-any cline-no">&nbsp;</span>
878
+ <span class="cline-any cline-no">&nbsp;</span>
879
+ <span class="cline-any cline-no">&nbsp;</span>
880
+ <span class="cline-any cline-no">&nbsp;</span>
881
+ <span class="cline-any cline-no">&nbsp;</span>
882
+ <span class="cline-any cline-no">&nbsp;</span>
883
+ <span class="cline-any cline-no">&nbsp;</span>
884
+ <span class="cline-any cline-no">&nbsp;</span>
885
+ <span class="cline-any cline-no">&nbsp;</span>
886
+ <span class="cline-any cline-no">&nbsp;</span>
887
+ <span class="cline-any cline-neutral">&nbsp;</span>
888
+ <span class="cline-any cline-no">&nbsp;</span>
889
+ <span class="cline-any cline-no">&nbsp;</span>
890
+ <span class="cline-any cline-no">&nbsp;</span>
891
+ <span class="cline-any cline-neutral">&nbsp;</span>
892
+ <span class="cline-any cline-no">&nbsp;</span>
893
+ <span class="cline-any cline-no">&nbsp;</span>
894
+ <span class="cline-any cline-no">&nbsp;</span>
895
+ <span class="cline-any cline-neutral">&nbsp;</span>
896
+ <span class="cline-any cline-neutral">&nbsp;</span>
897
+ <span class="cline-any cline-no">&nbsp;</span>
898
+ <span class="cline-any cline-no">&nbsp;</span>
899
+ <span class="cline-any cline-no">&nbsp;</span>
900
+ <span class="cline-any cline-no">&nbsp;</span>
901
+ <span class="cline-any cline-neutral">&nbsp;</span>
902
+ <span class="cline-any cline-neutral">&nbsp;</span>
903
+ <span class="cline-any cline-no">&nbsp;</span>
904
+ <span class="cline-any cline-no">&nbsp;</span>
905
+ <span class="cline-any cline-no">&nbsp;</span>
906
+ <span class="cline-any cline-no">&nbsp;</span>
907
+ <span class="cline-any cline-neutral">&nbsp;</span>
908
+ <span class="cline-any cline-neutral">&nbsp;</span>
909
+ <span class="cline-any cline-no">&nbsp;</span>
910
+ <span class="cline-any cline-no">&nbsp;</span>
911
+ <span class="cline-any cline-no">&nbsp;</span>
912
+ <span class="cline-any cline-no">&nbsp;</span>
913
+ <span class="cline-any cline-no">&nbsp;</span>
914
+ <span class="cline-any cline-no">&nbsp;</span>
915
+ <span class="cline-any cline-no">&nbsp;</span>
916
+ <span class="cline-any cline-no">&nbsp;</span>
917
+ <span class="cline-any cline-no">&nbsp;</span>
918
+ <span class="cline-any cline-no">&nbsp;</span>
919
+ <span class="cline-any cline-no">&nbsp;</span>
920
+ <span class="cline-any cline-neutral">&nbsp;</span>
921
+ <span class="cline-any cline-neutral">&nbsp;</span>
922
+ <span class="cline-any cline-neutral">&nbsp;</span>
923
+ <span class="cline-any cline-neutral">&nbsp;</span>
924
+ <span class="cline-any cline-no">&nbsp;</span>
925
+ <span class="cline-any cline-no">&nbsp;</span>
926
+ <span class="cline-any cline-no">&nbsp;</span>
927
+ <span class="cline-any cline-no">&nbsp;</span>
928
+ <span class="cline-any cline-no">&nbsp;</span>
929
+ <span class="cline-any cline-no">&nbsp;</span>
930
+ <span class="cline-any cline-no">&nbsp;</span>
931
+ <span class="cline-any cline-no">&nbsp;</span>
932
+ <span class="cline-any cline-no">&nbsp;</span>
933
+ <span class="cline-any cline-no">&nbsp;</span>
934
+ <span class="cline-any cline-no">&nbsp;</span>
935
+ <span class="cline-any cline-no">&nbsp;</span>
936
+ <span class="cline-any cline-neutral">&nbsp;</span>
937
+ <span class="cline-any cline-no">&nbsp;</span>
938
+ <span class="cline-any cline-no">&nbsp;</span>
939
+ <span class="cline-any cline-no">&nbsp;</span>
940
+ <span class="cline-any cline-no">&nbsp;</span>
941
+ <span class="cline-any cline-no">&nbsp;</span>
942
+ <span class="cline-any cline-no">&nbsp;</span>
943
+ <span class="cline-any cline-neutral">&nbsp;</span>
944
+ <span class="cline-any cline-no">&nbsp;</span>
945
+ <span class="cline-any cline-neutral">&nbsp;</span>
946
+ <span class="cline-any cline-no">&nbsp;</span>
947
+ <span class="cline-any cline-neutral">&nbsp;</span>
948
+ <span class="cline-any cline-no">&nbsp;</span>
949
+ <span class="cline-any cline-no">&nbsp;</span>
950
+ <span class="cline-any cline-no">&nbsp;</span>
951
+ <span class="cline-any cline-no">&nbsp;</span>
952
+ <span class="cline-any cline-no">&nbsp;</span>
953
+ <span class="cline-any cline-no">&nbsp;</span>
954
+ <span class="cline-any cline-no">&nbsp;</span>
955
+ <span class="cline-any cline-no">&nbsp;</span>
956
+ <span class="cline-any cline-no">&nbsp;</span>
957
+ <span class="cline-any cline-no">&nbsp;</span>
958
+ <span class="cline-any cline-no">&nbsp;</span>
959
+ <span class="cline-any cline-no">&nbsp;</span>
960
+ <span class="cline-any cline-no">&nbsp;</span>
961
+ <span class="cline-any cline-no">&nbsp;</span>
962
+ <span class="cline-any cline-no">&nbsp;</span>
963
+ <span class="cline-any cline-no">&nbsp;</span>
964
+ <span class="cline-any cline-neutral">&nbsp;</span>
965
+ <span class="cline-any cline-no">&nbsp;</span>
966
+ <span class="cline-any cline-no">&nbsp;</span>
967
+ <span class="cline-any cline-no">&nbsp;</span>
968
+ <span class="cline-any cline-no">&nbsp;</span>
969
+ <span class="cline-any cline-no">&nbsp;</span>
970
+ <span class="cline-any cline-no">&nbsp;</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-no">&nbsp;</span>
975
+ <span class="cline-any cline-no">&nbsp;</span>
976
+ <span class="cline-any cline-no">&nbsp;</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-no">&nbsp;</span>
980
+ <span class="cline-any cline-no">&nbsp;</span>
981
+ <span class="cline-any cline-no">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-no">&nbsp;</span>
986
+ <span class="cline-any cline-no">&nbsp;</span>
987
+ <span class="cline-any cline-no">&nbsp;</span>
988
+ <span class="cline-any cline-no">&nbsp;</span>
989
+ <span class="cline-any cline-no">&nbsp;</span>
990
+ <span class="cline-any cline-no">&nbsp;</span>
991
+ <span class="cline-any cline-no">&nbsp;</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-no">&nbsp;</span>
994
+ <span class="cline-any cline-no">&nbsp;</span>
995
+ <span class="cline-any cline-neutral">&nbsp;</span>
996
+ <span class="cline-any cline-no">&nbsp;</span>
997
+ <span class="cline-any cline-no">&nbsp;</span>
998
+ <span class="cline-any cline-no">&nbsp;</span>
999
+ <span class="cline-any cline-no">&nbsp;</span>
1000
+ <span class="cline-any cline-no">&nbsp;</span>
1001
+ <span class="cline-any cline-no">&nbsp;</span>
1002
+ <span class="cline-any cline-no">&nbsp;</span>
1003
+ <span class="cline-any cline-no">&nbsp;</span>
1004
+ <span class="cline-any cline-no">&nbsp;</span>
1005
+ <span class="cline-any cline-no">&nbsp;</span>
1006
+ <span class="cline-any cline-no">&nbsp;</span>
1007
+ <span class="cline-any cline-no">&nbsp;</span>
1008
+ <span class="cline-any cline-no">&nbsp;</span>
1009
+ <span class="cline-any cline-no">&nbsp;</span>
1010
+ <span class="cline-any cline-no">&nbsp;</span>
1011
+ <span class="cline-any cline-no">&nbsp;</span>
1012
+ <span class="cline-any cline-no">&nbsp;</span>
1013
+ <span class="cline-any cline-no">&nbsp;</span>
1014
+ <span class="cline-any cline-no">&nbsp;</span>
1015
+ <span class="cline-any cline-neutral">&nbsp;</span>
1016
+ <span class="cline-any cline-no">&nbsp;</span>
1017
+ <span class="cline-any cline-no">&nbsp;</span>
1018
+ <span class="cline-any cline-no">&nbsp;</span>
1019
+ <span class="cline-any cline-no">&nbsp;</span>
1020
+ <span class="cline-any cline-no">&nbsp;</span>
1021
+ <span class="cline-any cline-no">&nbsp;</span>
1022
+ <span class="cline-any cline-no">&nbsp;</span>
1023
+ <span class="cline-any cline-no">&nbsp;</span>
1024
+ <span class="cline-any cline-no">&nbsp;</span>
1025
+ <span class="cline-any cline-no">&nbsp;</span>
1026
+ <span class="cline-any cline-no">&nbsp;</span>
1027
+ <span class="cline-any cline-no">&nbsp;</span>
1028
+ <span class="cline-any cline-no">&nbsp;</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-no">&nbsp;</span>
1031
+ <span class="cline-any cline-no">&nbsp;</span>
1032
+ <span class="cline-any cline-no">&nbsp;</span>
1033
+ <span class="cline-any cline-no">&nbsp;</span>
1034
+ <span class="cline-any cline-no">&nbsp;</span>
1035
+ <span class="cline-any cline-no">&nbsp;</span>
1036
+ <span class="cline-any cline-no">&nbsp;</span>
1037
+ <span class="cline-any cline-neutral">&nbsp;</span>
1038
+ <span class="cline-any cline-neutral">&nbsp;</span>
1039
+ <span class="cline-any cline-neutral">&nbsp;</span>
1040
+ <span class="cline-any cline-neutral">&nbsp;</span>
1041
+ <span class="cline-any cline-no">&nbsp;</span>
1042
+ <span class="cline-any cline-neutral">&nbsp;</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-no">&nbsp;</span>
1045
+ <span class="cline-any cline-no">&nbsp;</span>
1046
+ <span class="cline-any cline-neutral">&nbsp;</span>
1047
+ <span class="cline-any cline-no">&nbsp;</span>
1048
+ <span class="cline-any cline-no">&nbsp;</span>
1049
+ <span class="cline-any cline-no">&nbsp;</span>
1050
+ <span class="cline-any cline-neutral">&nbsp;</span>
1051
+ <span class="cline-any cline-no">&nbsp;</span>
1052
+ <span class="cline-any cline-neutral">&nbsp;</span>
1053
+ <span class="cline-any cline-no">&nbsp;</span>
1054
+ <span class="cline-any cline-no">&nbsp;</span>
1055
+ <span class="cline-any cline-neutral">&nbsp;</span>
1056
+ <span class="cline-any cline-no">&nbsp;</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-no">&nbsp;</span>
1059
+ <span class="cline-any cline-no">&nbsp;</span>
1060
+ <span class="cline-any cline-no">&nbsp;</span>
1061
+ <span class="cline-any cline-no">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-neutral">&nbsp;</span>
1064
+ <span class="cline-any cline-no">&nbsp;</span>
1065
+ <span class="cline-any cline-no">&nbsp;</span>
1066
+ <span class="cline-any cline-no">&nbsp;</span>
1067
+ <span class="cline-any cline-no">&nbsp;</span>
1068
+ <span class="cline-any cline-no">&nbsp;</span>
1069
+ <span class="cline-any cline-no">&nbsp;</span>
1070
+ <span class="cline-any cline-no">&nbsp;</span>
1071
+ <span class="cline-any cline-no">&nbsp;</span>
1072
+ <span class="cline-any cline-no">&nbsp;</span>
1073
+ <span class="cline-any cline-no">&nbsp;</span>
1074
+ <span class="cline-any cline-no">&nbsp;</span>
1075
+ <span class="cline-any cline-no">&nbsp;</span>
1076
+ <span class="cline-any cline-neutral">&nbsp;</span>
1077
+ <span class="cline-any cline-no">&nbsp;</span>
1078
+ <span class="cline-any cline-no">&nbsp;</span>
1079
+ <span class="cline-any cline-no">&nbsp;</span>
1080
+ <span class="cline-any cline-no">&nbsp;</span>
1081
+ <span class="cline-any cline-no">&nbsp;</span>
1082
+ <span class="cline-any cline-no">&nbsp;</span>
1083
+ <span class="cline-any cline-no">&nbsp;</span>
1084
+ <span class="cline-any cline-no">&nbsp;</span>
1085
+ <span class="cline-any cline-no">&nbsp;</span>
1086
+ <span class="cline-any cline-no">&nbsp;</span>
1087
+ <span class="cline-any cline-no">&nbsp;</span>
1088
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
1089
+ *
1090
+ * MeterPro.ts: @switchbot/homebridge-switchbot.
1091
+ */
1092
+ import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
1093
+ import type { device, meterProCO2ServiceData, meterProCO2Status, meterProCO2WebhookContext, meterProServiceData, meterProStatus, meterProWebhookContext, SwitchBotBLE } from 'node-switchbot'
1094
+ &nbsp;
1095
+ import type { SwitchBotPlatform } from '../platform.js'
1096
+ import type { devicesConfig, meterProConfig } from '../settings.js'
1097
+ &nbsp;
1098
+ import { Units } from 'homebridge'
1099
+ /*
1100
+ * For Testing Locally:
1101
+ * import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
1102
+ */
1103
+ import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
1104
+ import { interval, skipWhile, Subject } from 'rxjs'
1105
+ &nbsp;
1106
+ import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js'
1107
+ import { deviceBase } from './device.js'
1108
+ &nbsp;
1109
+ /**
1110
+ * Platform Accessory
1111
+ * An instance of this class is created for each accessory your platform registers
1112
+ * Each accessory may expose multiple services of different service types.
1113
+ */
1114
+ export <span class="fstat-no" title="function not covered" ><span class="branch-0 cbranch-no" title="branch not covered" >class MeterPro extends deviceBase {</span></span>
1115
+ // Services
1116
+ <span class="cstat-no" title="statement not covered" > private Battery: {</span>
1117
+ Name: CharacteristicValue
1118
+ Service: Service
1119
+ BatteryLevel: CharacteristicValue
1120
+ StatusLowBattery: CharacteristicValue
1121
+ }
1122
+ &nbsp;
1123
+ <span class="cstat-no" title="statement not covered" > private HumiditySensor?: {</span>
1124
+ Name: CharacteristicValue
1125
+ Service: Service
1126
+ CurrentRelativeHumidity: CharacteristicValue
1127
+ }
1128
+ &nbsp;
1129
+ <span class="cstat-no" title="statement not covered" > private TemperatureSensor?: {</span>
1130
+ Name: CharacteristicValue
1131
+ Service: Service
1132
+ CurrentTemperature: CharacteristicValue
1133
+ }
1134
+ &nbsp;
1135
+ <span class="cstat-no" title="statement not covered" > private CarbonDioxideSensor?: {</span>
1136
+ Name: CharacteristicValue
1137
+ Service: Service
1138
+ CarbonDioxideDetected: CharacteristicValue
1139
+ CarbonDioxideLevel: CharacteristicValue
1140
+ }
1141
+ &nbsp;
1142
+ // OpenAPI
1143
+ <span class="cstat-no" title="statement not covered" > deviceStatus!: meterProStatus | meterProCO2Status</span>
1144
+ &nbsp;
1145
+ // Webhook
1146
+ <span class="cstat-no" title="statement not covered" > webhookContext!: meterProWebhookContext | meterProCO2WebhookContext</span>
1147
+ &nbsp;
1148
+ // BLE
1149
+ <span class="cstat-no" title="statement not covered" > serviceData!: meterProServiceData | meterProCO2ServiceData</span>
1150
+ &nbsp;
1151
+ // Updates
1152
+ <span class="cstat-no" title="statement not covered" > meterUpdateInProgress!: boolean</span>
1153
+ <span class="cstat-no" title="statement not covered" > doMeterUpdate: Subject&lt;void&gt;</span>
1154
+ &nbsp;
1155
+ <span class="cstat-no" title="statement not covered" > constructor(</span>
1156
+ <span class="cstat-no" title="statement not covered" > readonly platform: SwitchBotPlatform,</span>
1157
+ <span class="cstat-no" title="statement not covered" > accessory: PlatformAccessory,</span>
1158
+ <span class="cstat-no" title="statement not covered" > device: device &amp; devicesConfig,</span>
1159
+ <span class="cstat-no" title="statement not covered" > ) {</span>
1160
+ <span class="cstat-no" title="statement not covered" > super(platform, accessory, device)</span>
1161
+ // Set category
1162
+ <span class="cstat-no" title="statement not covered" > accessory.category = this.hap.Categories.SENSOR</span>
1163
+ &nbsp;
1164
+ // this is subject we use to track when we need to POST changes to the SwitchBot API
1165
+ <span class="cstat-no" title="statement not covered" > this.doMeterUpdate = new Subject()</span>
1166
+ <span class="cstat-no" title="statement not covered" > this.meterUpdateInProgress = false</span>
1167
+ &nbsp;
1168
+ // Initialize Battery Service
1169
+ <span class="cstat-no" title="statement not covered" > accessory.context.Battery = accessory.context.Battery ?? {}</span>
1170
+ <span class="cstat-no" title="statement not covered" > this.Battery = {</span>
1171
+ <span class="cstat-no" title="statement not covered" > Name: `${accessory.displayName} Battery`,</span>
1172
+ <span class="cstat-no" title="statement not covered" > Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,</span>
1173
+ <span class="cstat-no" title="statement not covered" > BatteryLevel: accessory.context.BatteryLevel ?? 100,</span>
1174
+ <span class="cstat-no" title="statement not covered" > StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,</span>
1175
+ <span class="cstat-no" title="statement not covered" > }</span>
1176
+ <span class="cstat-no" title="statement not covered" > accessory.context.Battery = this.Battery as object</span>
1177
+ &nbsp;
1178
+ // Initialize Battery Characteristics
1179
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() =&gt; {</span>
1180
+ <span class="cstat-no" title="statement not covered" > return this.Battery.BatteryLevel</span>
1181
+ <span class="cstat-no" title="statement not covered" > })</span>
1182
+ &nbsp;
1183
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() =&gt; {</span>
1184
+ <span class="cstat-no" title="statement not covered" > return this.Battery.StatusLowBattery</span>
1185
+ <span class="cstat-no" title="statement not covered" > })</span>
1186
+ &nbsp;
1187
+ // Initialize Temperature Sensor Service
1188
+ <span class="cstat-no" title="statement not covered" > if ((device as meterProConfig).hide_temperature) {</span>
1189
+ <span class="cstat-no" title="statement not covered" > if (this.TemperatureSensor) {</span>
1190
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Removing Temperature Sensor Service')</span>
1191
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.Service = this.accessory.getService(this.hap.Service.TemperatureSensor) as Service</span>
1192
+ <span class="cstat-no" title="statement not covered" > accessory.removeService(this.TemperatureSensor.Service)</span>
1193
+ <span class="cstat-no" title="statement not covered" > }</span>
1194
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1195
+ <span class="cstat-no" title="statement not covered" > accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {}</span>
1196
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor = {</span>
1197
+ <span class="cstat-no" title="statement not covered" > Name: `${accessory.displayName} Temperature Sensor`,</span>
1198
+ <span class="cstat-no" title="statement not covered" > Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,</span>
1199
+ <span class="cstat-no" title="statement not covered" > CurrentTemperature: accessory.context.CurrentTemperature ?? 30,</span>
1200
+ <span class="cstat-no" title="statement not covered" > }</span>
1201
+ <span class="cstat-no" title="statement not covered" > accessory.context.TemperatureSensor = this.TemperatureSensor as object</span>
1202
+ &nbsp;
1203
+ // Initialize Temperature Sensor Characteristics
1204
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.TemperatureSensor.Name).getCharacteristic(this.hap.Characteristic.CurrentTemperature).setProps({</span>
1205
+ <span class="cstat-no" title="statement not covered" > unit: Units.CELSIUS,</span>
1206
+ <span class="cstat-no" title="statement not covered" > validValueRanges: [-273.15, 100],</span>
1207
+ <span class="cstat-no" title="statement not covered" > minValue: -273.15,</span>
1208
+ <span class="cstat-no" title="statement not covered" > maxValue: 100,</span>
1209
+ <span class="cstat-no" title="statement not covered" > minStep: 0.1,</span>
1210
+ <span class="cstat-no" title="statement not covered" > }).onGet(() =&gt; {</span>
1211
+ <span class="cstat-no" title="statement not covered" > return this.TemperatureSensor!.CurrentTemperature!</span>
1212
+ <span class="cstat-no" title="statement not covered" > })</span>
1213
+ <span class="cstat-no" title="statement not covered" > }</span>
1214
+ // Initialize Humidity Sensor Service
1215
+ <span class="cstat-no" title="statement not covered" > if ((device as meterProConfig).hide_humidity) {</span>
1216
+ <span class="cstat-no" title="statement not covered" > if (this.HumiditySensor) {</span>
1217
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Removing Humidity Sensor Service')</span>
1218
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.Service = this.accessory.getService(this.hap.Service.HumiditySensor) as Service</span>
1219
+ <span class="cstat-no" title="statement not covered" > accessory.removeService(this.HumiditySensor.Service)</span>
1220
+ <span class="cstat-no" title="statement not covered" > }</span>
1221
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1222
+ <span class="cstat-no" title="statement not covered" > accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {}</span>
1223
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor = {</span>
1224
+ <span class="cstat-no" title="statement not covered" > Name: `${accessory.displayName} Humidity Sensor`,</span>
1225
+ <span class="cstat-no" title="statement not covered" > Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service,</span>
1226
+ <span class="cstat-no" title="statement not covered" > CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity ?? 50,</span>
1227
+ <span class="cstat-no" title="statement not covered" > }</span>
1228
+ <span class="cstat-no" title="statement not covered" > accessory.context.HumiditySensor = this.HumiditySensor as object</span>
1229
+ &nbsp;
1230
+ // Initialize Humidity Sensor Characteristics
1231
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.HumiditySensor.Name).getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity).setProps({</span>
1232
+ <span class="cstat-no" title="statement not covered" > minStep: 0.1,</span>
1233
+ <span class="cstat-no" title="statement not covered" > }).onGet(() =&gt; {</span>
1234
+ <span class="cstat-no" title="statement not covered" > return this.HumiditySensor!.CurrentRelativeHumidity!</span>
1235
+ <span class="cstat-no" title="statement not covered" > })</span>
1236
+ <span class="cstat-no" title="statement not covered" > }</span>
1237
+ &nbsp;
1238
+ // Initialize Carbon Dioxide Sensor Service
1239
+ <span class="cstat-no" title="statement not covered" > if ((device as meterProConfig).hide_co2) {</span>
1240
+ <span class="cstat-no" title="statement not covered" > if (this.CarbonDioxideSensor) {</span>
1241
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Removing Carbon Dioxide Sensor Service')</span>
1242
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.Service = this.accessory.getService(this.hap.Service.CarbonDioxideSensor) as Service</span>
1243
+ <span class="cstat-no" title="statement not covered" > accessory.removeService(this.CarbonDioxideSensor.Service)</span>
1244
+ <span class="cstat-no" title="statement not covered" > }</span>
1245
+ <span class="cstat-no" title="statement not covered" > } else if (this.device.deviceType === 'MeterPro(CO2)') {</span>
1246
+ <span class="cstat-no" title="statement not covered" > accessory.context.CarbonDioxideSensor = accessory.context.CarbonDioxideSensor ?? {}</span>
1247
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor = {</span>
1248
+ <span class="cstat-no" title="statement not covered" > Name: `${accessory.displayName} Carbon Dioxide Sensor`,</span>
1249
+ <span class="cstat-no" title="statement not covered" > Service: accessory.getService(this.hap.Service.CarbonDioxideSensor) ?? this.accessory.addService(this.hap.Service.CarbonDioxideSensor) as Service,</span>
1250
+ <span class="cstat-no" title="statement not covered" > CarbonDioxideDetected: accessory.context.CarbonDioxideDetected ?? this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL,</span>
1251
+ <span class="cstat-no" title="statement not covered" > CarbonDioxideLevel: accessory.context.CarbonDioxideLevel ?? 0,</span>
1252
+ <span class="cstat-no" title="statement not covered" > }</span>
1253
+ <span class="cstat-no" title="statement not covered" > accessory.context.CarbonDioxideSensor = this.CarbonDioxideSensor as object</span>
1254
+ &nbsp;
1255
+ // Initialize Carbon Dioxide Sensor Characteristics
1256
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.CarbonDioxideSensor.Name).getCharacteristic(this.hap.Characteristic.CarbonDioxideDetected).onGet(() =&gt; {</span>
1257
+ <span class="cstat-no" title="statement not covered" > return this.CarbonDioxideSensor!.CarbonDioxideDetected!</span>
1258
+ <span class="cstat-no" title="statement not covered" > })</span>
1259
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.Service.getCharacteristic(this.hap.Characteristic.CarbonDioxideLevel).setProps({</span>
1260
+ <span class="cstat-no" title="statement not covered" > minStep: 1,</span>
1261
+ <span class="cstat-no" title="statement not covered" > }).onGet(() =&gt; {</span>
1262
+ <span class="cstat-no" title="statement not covered" > return this.CarbonDioxideSensor!.CarbonDioxideLevel!</span>
1263
+ <span class="cstat-no" title="statement not covered" > })</span>
1264
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1265
+ <span class="cstat-no" title="statement not covered" > if (this.CarbonDioxideSensor) {</span>
1266
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Removing Carbon Dioxide Sensor Service')</span>
1267
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.Service = this.accessory.getService(this.hap.Service.CarbonDioxideSensor) as Service</span>
1268
+ <span class="cstat-no" title="statement not covered" > accessory.removeService(this.CarbonDioxideSensor.Service)</span>
1269
+ <span class="cstat-no" title="statement not covered" > }</span>
1270
+ <span class="cstat-no" title="statement not covered" > }</span>
1271
+ &nbsp;
1272
+ // Retrieve initial values and updateHomekit
1273
+ <span class="cstat-no" title="statement not covered" > try {</span>
1274
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Retrieve initial values and update Homekit')</span>
1275
+ <span class="cstat-no" title="statement not covered" > this.refreshStatus()</span>
1276
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1277
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e.message ?? e}`)</span>
1278
+ <span class="cstat-no" title="statement not covered" > }</span>
1279
+ &nbsp;
1280
+ // regisiter webhook event handler if enabled
1281
+ <span class="cstat-no" title="statement not covered" > try {</span>
1282
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Registering Webhook Event Handler')</span>
1283
+ <span class="cstat-no" title="statement not covered" > this.registerWebhook()</span>
1284
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1285
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to registerWebhook, Error: ${e.message ?? e}`)</span>
1286
+ <span class="cstat-no" title="statement not covered" > }</span>
1287
+ &nbsp;
1288
+ // regisiter platform BLE event handler if enabled
1289
+ <span class="cstat-no" title="statement not covered" > try {</span>
1290
+ <span class="cstat-no" title="statement not covered" > this.debugLog('Registering Platform BLE Event Handler')</span>
1291
+ <span class="cstat-no" title="statement not covered" > this.registerPlatformBLE()</span>
1292
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1293
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to registerPlatformBLE, Error: ${e.message ?? e}`)</span>
1294
+ <span class="cstat-no" title="statement not covered" > }</span>
1295
+ &nbsp;
1296
+ // Start an update interval
1297
+ <span class="cstat-no" title="statement not covered" > interval(this.deviceRefreshRate * 1000)</span>
1298
+ <span class="cstat-no" title="statement not covered" > .pipe(skipWhile(() =&gt; this.meterUpdateInProgress))</span>
1299
+ <span class="cstat-no" title="statement not covered" > .subscribe(async () =&gt; {</span>
1300
+ <span class="cstat-no" title="statement not covered" > await this.refreshStatus()</span>
1301
+ <span class="cstat-no" title="statement not covered" > })</span>
1302
+ <span class="cstat-no" title="statement not covered" > }</span>
1303
+ &nbsp;
1304
+ <span class="cstat-no" title="statement not covered" > async BLEparseStatus(): Promise&lt;void&gt; {</span>
1305
+ <span class="cstat-no" title="statement not covered" > this.debugLog('BLEparseStatus')</span>
1306
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`(temperature, humidity${this.device.deviceType === 'MeterPro(CO2)' ? ', co2' : ''}) = BLE:(${this.serviceData.celsius}, ${this.serviceData.humidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${(this.serviceData as meterProCO2ServiceData).co2}` : ''}) current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${this.CarbonDioxideSensor?.CarbonDioxideLevel}` : ''})`)</span>
1307
+ &nbsp;
1308
+ // CurrentRelativeHumidity
1309
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1310
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity, 0, 100)</span>
1311
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`)</span>
1312
+ <span class="cstat-no" title="statement not covered" > }</span>
1313
+ // Current Temperature
1314
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1315
+ <span class="cstat-no" title="statement not covered" > const CELSIUS = this.serviceData.celsius &lt; 0 ? 0 : this.serviceData.celsius &gt; 100 ? 100 : this.serviceData.celsius</span>
1316
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.CurrentTemperature = CELSIUS</span>
1317
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)</span>
1318
+ <span class="cstat-no" title="statement not covered" > }</span>
1319
+ // Carbon Dioxide Sensor
1320
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_co2 &amp;&amp; this.CarbonDioxideSensor?.Service &amp;&amp; this.device.deviceType === 'MeterPro(CO2)') {</span>
1321
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideLevel = (this.serviceData as meterProCO2ServiceData).co2</span>
1322
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideLevel: ${this.CarbonDioxideSensor.CarbonDioxideLevel}ppm`)</span>
1323
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideDetected = this.CarbonDioxideSensor.CarbonDioxideLevel &gt; 0</span>
1324
+ <span class="cstat-no" title="statement not covered" > ? this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_ABNORMAL</span>
1325
+ <span class="cstat-no" title="statement not covered" > : this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL</span>
1326
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideDetected: ${this.CarbonDioxideSensor.CarbonDioxideDetected}`)</span>
1327
+ <span class="cstat-no" title="statement not covered" > this.warnLog('Carbon Dioxide Sensor is not supported yet.')</span>
1328
+ <span class="cstat-no" title="statement not covered" > }</span>
1329
+ // Battery Info
1330
+ <span class="cstat-no" title="statement not covered" > if ('battery' in this.serviceData) {</span>
1331
+ // BatteryLevel
1332
+ <span class="cstat-no" title="statement not covered" > this.Battery.BatteryLevel = this.serviceData.battery</span>
1333
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)</span>
1334
+ // StatusLowBattery
1335
+ <span class="cstat-no" title="statement not covered" > this.Battery.StatusLowBattery = this.Battery.BatteryLevel &lt; 10</span>
1336
+ <span class="cstat-no" title="statement not covered" > ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW</span>
1337
+ <span class="cstat-no" title="statement not covered" > : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL</span>
1338
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)</span>
1339
+ <span class="cstat-no" title="statement not covered" > }</span>
1340
+ <span class="cstat-no" title="statement not covered" > }</span>
1341
+ &nbsp;
1342
+ <span class="cstat-no" title="statement not covered" > async openAPIparseStatus(): Promise&lt;void&gt; {</span>
1343
+ <span class="cstat-no" title="statement not covered" > this.debugLog('openAPIparseStatus')</span>
1344
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`(temperature, humidity${this.device.deviceType === 'MeterPro(CO2)' ? ', co2' : ''}) = OpenAPI:(${this.deviceStatus.temperature}, ${this.deviceStatus.humidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${(this.deviceStatus as meterProCO2Status).CO2}` : ''}) current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${this.CarbonDioxideSensor?.CarbonDioxideLevel}` : ''})`)</span>
1345
+ &nbsp;
1346
+ // CurrentRelativeHumidity
1347
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1348
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.CurrentRelativeHumidity = this.deviceStatus.humidity</span>
1349
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`)</span>
1350
+ <span class="cstat-no" title="statement not covered" > }</span>
1351
+ &nbsp;
1352
+ // CurrentTemperature
1353
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1354
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature</span>
1355
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)</span>
1356
+ <span class="cstat-no" title="statement not covered" > }</span>
1357
+ &nbsp;
1358
+ // Carbon Dioxide Sensor
1359
+ <span class="cstat-no" title="statement not covered" > this.warnLog(`(before, after) CarbonDioxideLevel: (${this.CarbonDioxideSensor?.CarbonDioxideLevel},${(this.webhookContext as meterProCO2WebhookContext).CO2})`)</span>
1360
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_co2 &amp;&amp; this.CarbonDioxideSensor?.Service &amp;&amp; this.device.deviceType === 'MeterPro(CO2)') {</span>
1361
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideLevel = (this.deviceStatus as meterProCO2Status).CO2</span>
1362
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideLevel: ${this.CarbonDioxideSensor.CarbonDioxideLevel}ppm`)</span>
1363
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideDetected = this.CarbonDioxideSensor.CarbonDioxideLevel &gt; 0</span>
1364
+ <span class="cstat-no" title="statement not covered" > ? this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_ABNORMAL</span>
1365
+ <span class="cstat-no" title="statement not covered" > : this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL</span>
1366
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideDetected: ${this.CarbonDioxideSensor.CarbonDioxideDetected}`)</span>
1367
+ <span class="cstat-no" title="statement not covered" > this.warnLog('Carbon Dioxide Sensor is not supported yet.')</span>
1368
+ <span class="cstat-no" title="statement not covered" > }</span>
1369
+ &nbsp;
1370
+ // Battery Info
1371
+ <span class="cstat-no" title="statement not covered" > if ('battery' in this.deviceStatus) {</span>
1372
+ // BatteryLevel
1373
+ <span class="cstat-no" title="statement not covered" > this.Battery.BatteryLevel = this.deviceStatus.battery</span>
1374
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)</span>
1375
+ &nbsp;
1376
+ // StatusLowBattery
1377
+ <span class="cstat-no" title="statement not covered" > this.Battery.StatusLowBattery = this.Battery.BatteryLevel &lt; 10</span>
1378
+ <span class="cstat-no" title="statement not covered" > ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW</span>
1379
+ <span class="cstat-no" title="statement not covered" > : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL</span>
1380
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)</span>
1381
+ <span class="cstat-no" title="statement not covered" > }</span>
1382
+ &nbsp;
1383
+ // FirmwareVersion
1384
+ <span class="cstat-no" title="statement not covered" > if (this.deviceStatus.version) {</span>
1385
+ <span class="cstat-no" title="statement not covered" > const version = this.deviceStatus.version as string</span>
1386
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`)</span>
1387
+ <span class="cstat-no" title="statement not covered" > const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'</span>
1388
+ <span class="cstat-no" title="statement not covered" > this.accessory</span>
1389
+ <span class="cstat-no" title="statement not covered" > .getService(this.hap.Service.AccessoryInformation)!</span>
1390
+ <span class="cstat-no" title="statement not covered" > .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)</span>
1391
+ <span class="cstat-no" title="statement not covered" > .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)</span>
1392
+ <span class="cstat-no" title="statement not covered" > .getCharacteristic(this.hap.Characteristic.FirmwareRevision)</span>
1393
+ <span class="cstat-no" title="statement not covered" > .updateValue(deviceVersion)</span>
1394
+ <span class="cstat-no" title="statement not covered" > this.accessory.context.version = deviceVersion</span>
1395
+ <span class="cstat-no" title="statement not covered" > this.debugSuccessLog(`v: ${this.accessory.context.version}`)</span>
1396
+ <span class="cstat-no" title="statement not covered" > }</span>
1397
+ <span class="cstat-no" title="statement not covered" > }</span>
1398
+ &nbsp;
1399
+ <span class="cstat-no" title="statement not covered" > async parseStatusWebhook(): Promise&lt;void&gt; {</span>
1400
+ <span class="cstat-no" title="statement not covered" > this.debugLog('parseStatusWebhook')</span>
1401
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`(scale, temperature, humidity${this.device.deviceType === 'MeterPro(CO2)' ? ', co2' : ''}) = Webhook:(${this.webhookContext.scale}, ${convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterProConfig).convertUnitTo)}, ${this.webhookContext.humidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${(this.webhookContext as meterProCO2WebhookContext).CO2}` : ''}) current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity}${this.device.deviceType === 'MeterPro(CO2)' ? `, ${this.CarbonDioxideSensor?.CarbonDioxideLevel}` : ''})`)</span>
1402
+ // Check if the scale is not CELSIUS
1403
+ <span class="cstat-no" title="statement not covered" > if (this.webhookContext.scale !== 'CELSIUS' &amp;&amp; (this.device as meterProConfig).convertUnitTo === undefined) {</span>
1404
+ <span class="cstat-no" title="statement not covered" > this.warnLog(`received a non-CELSIUS Webhook scale: ${this.webhookContext.scale}, Use the *convertUnitsTo* config under Hub settings, if displaying incorrectly in HomeKit.`)</span>
1405
+ <span class="cstat-no" title="statement not covered" > }</span>
1406
+ &nbsp;
1407
+ // CurrentRelativeHumidity
1408
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1409
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.CurrentRelativeHumidity = this.webhookContext.humidity</span>
1410
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`)</span>
1411
+ <span class="cstat-no" title="statement not covered" > }</span>
1412
+ &nbsp;
1413
+ // CurrentTemperature
1414
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1415
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.CurrentTemperature = convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterProConfig).convertUnitTo)</span>
1416
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`)</span>
1417
+ <span class="cstat-no" title="statement not covered" > }</span>
1418
+ &nbsp;
1419
+ // Carbon Dioxide Sensor
1420
+ <span class="cstat-no" title="statement not covered" > this.warnLog(`(before, after) CarbonDioxideLevel: (${this.CarbonDioxideSensor?.CarbonDioxideLevel},${(this.webhookContext as meterProCO2WebhookContext).CO2})`)</span>
1421
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_co2 &amp;&amp; this.CarbonDioxideSensor?.Service &amp;&amp; this.device.deviceType === 'MeterPro(CO2)') {</span>
1422
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideLevel = (this.webhookContext as meterProCO2WebhookContext).CO2</span>
1423
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideLevel: ${this.CarbonDioxideSensor.CarbonDioxideLevel}ppm`)</span>
1424
+ <span class="cstat-no" title="statement not covered" > this.CarbonDioxideSensor.CarbonDioxideDetected = this.CarbonDioxideSensor.CarbonDioxideLevel &gt; 0</span>
1425
+ <span class="cstat-no" title="statement not covered" > ? this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_ABNORMAL</span>
1426
+ <span class="cstat-no" title="statement not covered" > : this.hap.Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL</span>
1427
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`CarbonDioxideDetected: ${this.CarbonDioxideSensor.CarbonDioxideDetected}`)</span>
1428
+ <span class="cstat-no" title="statement not covered" > this.warnLog('Carbon Dioxide Sensor is not supported yet.')</span>
1429
+ <span class="cstat-no" title="statement not covered" > }</span>
1430
+ <span class="cstat-no" title="statement not covered" > }</span>
1431
+ &nbsp;
1432
+ /**
1433
+ * Asks the SwitchBot API for the latest device information
1434
+ */
1435
+ <span class="cstat-no" title="statement not covered" > async refreshStatus(): Promise&lt;void&gt; {</span>
1436
+ <span class="cstat-no" title="statement not covered" > if (!this.device.enableCloudService &amp;&amp; this.OpenAPI) {</span>
1437
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`)</span>
1438
+ <span class="cstat-no" title="statement not covered" > } else if (this.BLE) {</span>
1439
+ <span class="cstat-no" title="statement not covered" > await this.BLERefreshStatus()</span>
1440
+ <span class="cstat-no" title="statement not covered" > } else if (this.OpenAPI &amp;&amp; this.platform.config.credentials?.token) {</span>
1441
+ <span class="cstat-no" title="statement not covered" > await this.openAPIRefreshStatus()</span>
1442
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1443
+ <span class="cstat-no" title="statement not covered" > await this.offlineOff()</span>
1444
+ <span class="cstat-no" title="statement not covered" > this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)</span>
1445
+ <span class="cstat-no" title="statement not covered" > }</span>
1446
+ <span class="cstat-no" title="statement not covered" > }</span>
1447
+ &nbsp;
1448
+ <span class="cstat-no" title="statement not covered" > async BLERefreshStatus(): Promise&lt;void&gt; {</span>
1449
+ <span class="cstat-no" title="statement not covered" > this.debugLog('BLERefreshStatus')</span>
1450
+ <span class="cstat-no" title="statement not covered" > const switchBotBLE = await this.switchbotBLE()</span>
1451
+ <span class="cstat-no" title="statement not covered" > if (switchBotBLE === undefined) {</span>
1452
+ <span class="cstat-no" title="statement not covered" > await this.BLERefreshConnection(switchBotBLE)</span>
1453
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1454
+ // Start to monitor advertisement packets
1455
+ <span class="cstat-no" title="statement not covered" > (async () =&gt; {</span>
1456
+ // Start to monitor advertisement packets
1457
+ <span class="cstat-no" title="statement not covered" > const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as meterProServiceData | meterProCO2ServiceData</span>
1458
+ // Update HomeKit
1459
+ <span class="cstat-no" title="statement not covered" > if (serviceData.model === SwitchBotBLEModel.MeterPro &amp;&amp; serviceData.modelName === SwitchBotBLEModelName.MeterPro) {</span>
1460
+ <span class="cstat-no" title="statement not covered" > this.serviceData = serviceData</span>
1461
+ <span class="cstat-no" title="statement not covered" > if (serviceData !== undefined || serviceData !== null) {</span>
1462
+ <span class="cstat-no" title="statement not covered" > await this.BLEparseStatus()</span>
1463
+ <span class="cstat-no" title="statement not covered" > await this.updateHomeKitCharacteristics()</span>
1464
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1465
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`serviceData is either undefined or null, serviceData: ${JSON.stringify(serviceData)}`)</span>
1466
+ <span class="cstat-no" title="statement not covered" > await this.BLERefreshConnection(switchBotBLE)</span>
1467
+ <span class="cstat-no" title="statement not covered" > }</span>
1468
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1469
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to get serviceData, serviceData: ${JSON.stringify(serviceData)}`)</span>
1470
+ <span class="cstat-no" title="statement not covered" > await this.BLERefreshConnection(switchBotBLE)</span>
1471
+ <span class="cstat-no" title="statement not covered" > }</span>
1472
+ <span class="cstat-no" title="statement not covered" > })()</span>
1473
+ <span class="cstat-no" title="statement not covered" > }</span>
1474
+ <span class="cstat-no" title="statement not covered" > }</span>
1475
+ &nbsp;
1476
+ <span class="cstat-no" title="statement not covered" > async registerPlatformBLE(): Promise&lt;void&gt; {</span>
1477
+ <span class="cstat-no" title="statement not covered" > this.debugLog('registerPlatformBLE')</span>
1478
+ <span class="cstat-no" title="statement not covered" > if (this.config.options?.BLE &amp;&amp; !this.device.disablePlatformBLE) {</span>
1479
+ <span class="cstat-no" title="statement not covered" > this.debugLog('is listening to Platform BLE.')</span>
1480
+ <span class="cstat-no" title="statement not covered" > try {</span>
1481
+ <span class="cstat-no" title="statement not covered" > const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId)</span>
1482
+ <span class="cstat-no" title="statement not covered" > this.device.bleMac = formattedDeviceId</span>
1483
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`bleMac: ${this.device.bleMac}`)</span>
1484
+ <span class="cstat-no" title="statement not covered" > this.platform.bleEventHandler[this.device.bleMac] = async (context: meterProServiceData) =&gt; {</span>
1485
+ <span class="cstat-no" title="statement not covered" > try {</span>
1486
+ <span class="cstat-no" title="statement not covered" > this.serviceData = context</span>
1487
+ <span class="cstat-no" title="statement not covered" > if (context !== undefined || context !== null) {</span>
1488
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`received BLE: ${JSON.stringify(context)}`)</span>
1489
+ <span class="cstat-no" title="statement not covered" > await this.BLEparseStatus()</span>
1490
+ <span class="cstat-no" title="statement not covered" > await this.updateHomeKitCharacteristics()</span>
1491
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1492
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`context is either undefined or null, context: ${JSON.stringify(context)}`)</span>
1493
+ <span class="cstat-no" title="statement not covered" > await this.BLERefreshConnection(context)</span>
1494
+ <span class="cstat-no" title="statement not covered" > }</span>
1495
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1496
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)</span>
1497
+ <span class="cstat-no" title="statement not covered" > }</span>
1498
+ <span class="cstat-no" title="statement not covered" > }</span>
1499
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1500
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to format device ID as MAC, Error: ${error}`)</span>
1501
+ <span class="cstat-no" title="statement not covered" > }</span>
1502
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1503
+ <span class="cstat-no" title="statement not covered" > this.debugLog('is not listening to Platform BLE')</span>
1504
+ <span class="cstat-no" title="statement not covered" > }</span>
1505
+ <span class="cstat-no" title="statement not covered" > }</span>
1506
+ &nbsp;
1507
+ <span class="cstat-no" title="statement not covered" > async openAPIRefreshStatus(): Promise&lt;void&gt; {</span>
1508
+ <span class="cstat-no" title="statement not covered" > this.debugLog('openAPIRefreshStatus')</span>
1509
+ <span class="cstat-no" title="statement not covered" > try {</span>
1510
+ <span class="cstat-no" title="statement not covered" > const response = await this.deviceRefreshStatus()</span>
1511
+ <span class="cstat-no" title="statement not covered" > const deviceStatus: any = response.body</span>
1512
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)</span>
1513
+ <span class="cstat-no" title="statement not covered" > if (await this.successfulStatusCodes(deviceStatus)) {</span>
1514
+ <span class="cstat-no" title="statement not covered" > this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)</span>
1515
+ <span class="cstat-no" title="statement not covered" > this.deviceStatus = deviceStatus.body</span>
1516
+ <span class="cstat-no" title="statement not covered" > await this.openAPIparseStatus()</span>
1517
+ <span class="cstat-no" title="statement not covered" > await this.updateHomeKitCharacteristics()</span>
1518
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1519
+ <span class="cstat-no" title="statement not covered" > this.debugWarnLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)</span>
1520
+ <span class="cstat-no" title="statement not covered" > }</span>
1521
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1522
+ <span class="cstat-no" title="statement not covered" > await this.apiError(e)</span>
1523
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)</span>
1524
+ <span class="cstat-no" title="statement not covered" > }</span>
1525
+ <span class="cstat-no" title="statement not covered" > }</span>
1526
+ &nbsp;
1527
+ <span class="cstat-no" title="statement not covered" > async registerWebhook() {</span>
1528
+ <span class="cstat-no" title="statement not covered" > if (this.device.webhook) {</span>
1529
+ <span class="cstat-no" title="statement not covered" > this.debugLog('is listening webhook.')</span>
1530
+ <span class="cstat-no" title="statement not covered" > this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterProWebhookContext) =&gt; {</span>
1531
+ <span class="cstat-no" title="statement not covered" > try {</span>
1532
+ <span class="cstat-no" title="statement not covered" > this.webhookContext = context</span>
1533
+ <span class="cstat-no" title="statement not covered" > if (context !== undefined || context !== null) {</span>
1534
+ <span class="cstat-no" title="statement not covered" > this.debugLog(`received Webhook: ${JSON.stringify(context)}`)</span>
1535
+ <span class="cstat-no" title="statement not covered" > await this.parseStatusWebhook()</span>
1536
+ <span class="cstat-no" title="statement not covered" > await this.updateHomeKitCharacteristics()</span>
1537
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1538
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`context is either undefined or null, context: ${JSON.stringify(context)}`)</span>
1539
+ <span class="cstat-no" title="statement not covered" > }</span>
1540
+ <span class="cstat-no" title="statement not covered" > } catch (e: any) {</span>
1541
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)</span>
1542
+ <span class="cstat-no" title="statement not covered" > }</span>
1543
+ <span class="cstat-no" title="statement not covered" > }</span>
1544
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1545
+ <span class="cstat-no" title="statement not covered" > this.debugLog('is not listening webhook.')</span>
1546
+ <span class="cstat-no" title="statement not covered" > }</span>
1547
+ <span class="cstat-no" title="statement not covered" > }</span>
1548
+ &nbsp;
1549
+ /**
1550
+ * Updates the status for each of the HomeKit Characteristics
1551
+ */
1552
+ <span class="cstat-no" title="statement not covered" > async updateHomeKitCharacteristics(): Promise&lt;void&gt; {</span>
1553
+ // CurrentRelativeHumidity
1554
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1555
+ <span class="cstat-no" title="statement not covered" > await this.updateCharacteristic(this.HumiditySensor.Service, this.hap.Characteristic.CurrentRelativeHumidity, this.HumiditySensor.CurrentRelativeHumidity, 'CurrentRelativeHumidity')</span>
1556
+ <span class="cstat-no" title="statement not covered" > }</span>
1557
+ // CurrentTemperature
1558
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1559
+ <span class="cstat-no" title="statement not covered" > await this.updateCharacteristic(this.TemperatureSensor.Service, this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor.CurrentTemperature, 'CurrentTemperature')</span>
1560
+ <span class="cstat-no" title="statement not covered" > }</span>
1561
+ // BatteryLevel
1562
+ <span class="cstat-no" title="statement not covered" > await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel')</span>
1563
+ // StatusLowBattery
1564
+ <span class="cstat-no" title="statement not covered" > await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery')</span>
1565
+ <span class="cstat-no" title="statement not covered" > }</span>
1566
+ &nbsp;
1567
+ <span class="cstat-no" title="statement not covered" > async BLERefreshConnection(switchbot: SwitchBotBLE): Promise&lt;void&gt; {</span>
1568
+ <span class="cstat-no" title="statement not covered" > this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)</span>
1569
+ <span class="cstat-no" title="statement not covered" > if (this.platform.config.credentials?.token &amp;&amp; this.device.connectionType === 'BLE/OpenAPI') {</span>
1570
+ <span class="cstat-no" title="statement not covered" > this.warnLog('Using OpenAPI Connection to Refresh Status')</span>
1571
+ <span class="cstat-no" title="statement not covered" > await this.openAPIRefreshStatus()</span>
1572
+ <span class="cstat-no" title="statement not covered" > }</span>
1573
+ <span class="cstat-no" title="statement not covered" > }</span>
1574
+ &nbsp;
1575
+ <span class="cstat-no" title="statement not covered" > async offlineOff(): Promise&lt;void&gt; {</span>
1576
+ <span class="cstat-no" title="statement not covered" > if (this.device.offline) {</span>
1577
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1578
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, 50)</span>
1579
+ <span class="cstat-no" title="statement not covered" > }</span>
1580
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1581
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, 30)</span>
1582
+ <span class="cstat-no" title="statement not covered" > }</span>
1583
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, 100)</span>
1584
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL)</span>
1585
+ <span class="cstat-no" title="statement not covered" > }</span>
1586
+ <span class="cstat-no" title="statement not covered" > }</span>
1587
+ &nbsp;
1588
+ <span class="cstat-no" title="statement not covered" > async apiError(e: any): Promise&lt;void&gt; {</span>
1589
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_humidity &amp;&amp; this.HumiditySensor?.Service) {</span>
1590
+ <span class="cstat-no" title="statement not covered" > this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e)</span>
1591
+ <span class="cstat-no" title="statement not covered" > }</span>
1592
+ <span class="cstat-no" title="statement not covered" > if (!(this.device as meterProConfig).hide_temperature &amp;&amp; this.TemperatureSensor?.Service) {</span>
1593
+ <span class="cstat-no" title="statement not covered" > this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e)</span>
1594
+ <span class="cstat-no" title="statement not covered" > }</span>
1595
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)</span>
1596
+ <span class="cstat-no" title="statement not covered" > this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)</span>
1597
+ <span class="cstat-no" title="statement not covered" > }</span>
1598
+ <span class="cstat-no" title="statement not covered" >}</span>
1599
+ &nbsp;</pre></td></tr></table></pre>
1600
+
1601
+ <div class='push'></div><!-- for sticky footer -->
1602
+ </div><!-- /wrapper -->
1603
+ <div class='footer quiet pad2 space-top1 center small'>
1604
+ Code coverage generated by
1605
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1606
+ at 2025-08-21T05:12:41.588Z
1607
+ </div>
1608
+ <script src="../../prettify.js"></script>
1609
+ <script>
1610
+ window.onload = function () {
1611
+ prettyPrint();
1612
+ };
1613
+ </script>
1614
+ <script src="../../sorter.js"></script>
1615
+ <script src="../../block-navigation.js"></script>
1616
+ </body>
1617
+ </html>
1618
+