rsmp 0.47.0 → 0.48.0

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 (426) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/copilot-setup-steps.yml +1 -1
  3. data/.github/workflows/rubocop.yaml +1 -1
  4. data/.github/workflows/sus.yaml +1 -1
  5. data/CHANGELOG.md +10 -0
  6. data/Gemfile.lock +5 -5
  7. data/README.md +3 -1
  8. data/documentation/cli.md +225 -0
  9. data/documentation/configuration.md +57 -0
  10. data/lib/rsmp/cli/configuration.rb +30 -0
  11. data/lib/rsmp/cli.rb +18 -45
  12. data/lib/rsmp/collect/command_matcher.rb +13 -4
  13. data/lib/rsmp/collect/status_matcher.rb +14 -4
  14. data/lib/rsmp/command_list.rb +1 -1
  15. data/lib/rsmp/convert/export/json_schema/index.rb +64 -0
  16. data/lib/rsmp/convert/export/json_schema/items.rb +9 -1
  17. data/lib/rsmp/convert/export/json_schema/outputs.rb +65 -25
  18. data/lib/rsmp/convert/export/json_schema/values.rb +40 -11
  19. data/lib/rsmp/convert/export/json_schema.rb +3 -1
  20. data/lib/rsmp/message/sxl_codec.rb +194 -0
  21. data/lib/rsmp/message.rb +2 -0
  22. data/lib/rsmp/node/site/connections.rb +80 -0
  23. data/lib/rsmp/node/site/site.rb +21 -35
  24. data/lib/rsmp/node/supervisor/supervisor.rb +42 -0
  25. data/lib/rsmp/options/schemas/site.json +3 -0
  26. data/lib/rsmp/options/schemas/supervisor.json +1 -0
  27. data/lib/rsmp/options/site_options.rb +30 -21
  28. data/lib/rsmp/options/supervisor_options.rb +1 -0
  29. data/lib/rsmp/proxy/modules/receive.rb +3 -1
  30. data/lib/rsmp/proxy/modules/send.rb +26 -14
  31. data/lib/rsmp/proxy/proxy.rb +17 -0
  32. data/lib/rsmp/proxy/site/connection.rb +79 -0
  33. data/lib/rsmp/proxy/site/modules/commands.rb +24 -1
  34. data/lib/rsmp/proxy/site/site_proxy.rb +6 -15
  35. data/lib/rsmp/proxy/supervisor/modules/commands.rb +55 -0
  36. data/lib/rsmp/proxy/supervisor/modules/status.rb +13 -104
  37. data/lib/rsmp/proxy/supervisor/modules/status_updates.rb +148 -0
  38. data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +19 -0
  39. data/lib/rsmp/schema.rb +38 -1
  40. data/lib/rsmp/tlc/detector_logic.rb +2 -2
  41. data/lib/rsmp/tlc/modules/helpers.rb +0 -22
  42. data/lib/rsmp/tlc/modules/inputs.rb +4 -3
  43. data/lib/rsmp/tlc/modules/modes.rb +2 -2
  44. data/lib/rsmp/tlc/modules/plans.rb +7 -3
  45. data/lib/rsmp/tlc/modules/system.rb +1 -1
  46. data/lib/rsmp/tlc/proxy/control.rb +19 -19
  47. data/lib/rsmp/tlc/proxy/detectors.rb +3 -3
  48. data/lib/rsmp/tlc/proxy/io.rb +15 -12
  49. data/lib/rsmp/tlc/proxy/plans.rb +14 -14
  50. data/lib/rsmp/tlc/proxy/status.rb +9 -5
  51. data/lib/rsmp/tlc/proxy/system.rb +12 -6
  52. data/lib/rsmp/tlc/signal_group.rb +2 -2
  53. data/lib/rsmp/tlc/supervisor_interface.rb +42 -0
  54. data/lib/rsmp/tlc/traffic_controller_site.rb +1 -18
  55. data/lib/rsmp/version.rb +1 -1
  56. data/lib/rsmp.rb +4 -0
  57. data/schemas/core/3.1.4/command_response.json +11 -0
  58. data/schemas/core/3.1.5/command_response.json +11 -0
  59. data/schemas/core/3.2.0/command_response.json +11 -0
  60. data/schemas/core/3.2.1/command_response.json +11 -0
  61. data/schemas/core/3.2.2/command_response.json +11 -0
  62. data/schemas/core/3.3.0/command_response.json +11 -0
  63. data/schemas/tlc/1.0.10/alarms/A0008.json +21 -15
  64. data/schemas/tlc/1.0.10/alarms/A0201.json +26 -20
  65. data/schemas/tlc/1.0.10/alarms/A0202.json +26 -20
  66. data/schemas/tlc/1.0.10/alarms/A0301.json +69 -63
  67. data/schemas/tlc/1.0.10/alarms/A0302.json +87 -81
  68. data/schemas/tlc/1.0.10/commands/M0001.json +66 -60
  69. data/schemas/tlc/1.0.10/commands/M0002.json +48 -42
  70. data/schemas/tlc/1.0.10/commands/M0003.json +48 -42
  71. data/schemas/tlc/1.0.10/commands/M0004.json +35 -29
  72. data/schemas/tlc/1.0.10/commands/M0005.json +48 -42
  73. data/schemas/tlc/1.0.10/commands/M0006.json +48 -42
  74. data/schemas/tlc/1.0.10/commands/M0007.json +35 -29
  75. data/schemas/tlc/1.0.10/commands/M0008.json +48 -42
  76. data/schemas/tlc/1.0.10/commands/M0010.json +35 -29
  77. data/schemas/tlc/1.0.10/commands/M0011.json +35 -29
  78. data/schemas/tlc/1.0.10/commands/M0012.json +35 -29
  79. data/schemas/tlc/1.0.10/commands/M0013.json +35 -29
  80. data/schemas/tlc/1.0.10/commands/M0019.json +61 -55
  81. data/schemas/tlc/1.0.10/commands/M0103.json +51 -45
  82. data/schemas/tlc/1.0.10/commands/M0104.json +100 -94
  83. data/schemas/tlc/1.0.10/commands/command_requests.json +995 -1
  84. data/schemas/tlc/1.0.10/defs/guards.json +19 -0
  85. data/schemas/tlc/1.0.10/sxl.yaml +56 -56
  86. data/schemas/tlc/1.0.10/sxl_index.json +226 -244
  87. data/schemas/tlc/1.0.13/alarms/A0008.json +21 -15
  88. data/schemas/tlc/1.0.13/alarms/A0201.json +26 -20
  89. data/schemas/tlc/1.0.13/alarms/A0202.json +26 -20
  90. data/schemas/tlc/1.0.13/alarms/A0301.json +69 -63
  91. data/schemas/tlc/1.0.13/alarms/A0302.json +87 -81
  92. data/schemas/tlc/1.0.13/commands/M0001.json +66 -60
  93. data/schemas/tlc/1.0.13/commands/M0002.json +48 -42
  94. data/schemas/tlc/1.0.13/commands/M0003.json +48 -42
  95. data/schemas/tlc/1.0.13/commands/M0004.json +35 -29
  96. data/schemas/tlc/1.0.13/commands/M0005.json +48 -42
  97. data/schemas/tlc/1.0.13/commands/M0006.json +48 -42
  98. data/schemas/tlc/1.0.13/commands/M0007.json +35 -29
  99. data/schemas/tlc/1.0.13/commands/M0008.json +48 -42
  100. data/schemas/tlc/1.0.13/commands/M0010.json +35 -29
  101. data/schemas/tlc/1.0.13/commands/M0011.json +35 -29
  102. data/schemas/tlc/1.0.13/commands/M0012.json +35 -29
  103. data/schemas/tlc/1.0.13/commands/M0013.json +35 -29
  104. data/schemas/tlc/1.0.13/commands/M0014.json +48 -42
  105. data/schemas/tlc/1.0.13/commands/M0015.json +48 -42
  106. data/schemas/tlc/1.0.13/commands/M0016.json +35 -29
  107. data/schemas/tlc/1.0.13/commands/M0017.json +35 -29
  108. data/schemas/tlc/1.0.13/commands/M0018.json +48 -42
  109. data/schemas/tlc/1.0.13/commands/M0019.json +61 -55
  110. data/schemas/tlc/1.0.13/commands/M0103.json +51 -45
  111. data/schemas/tlc/1.0.13/commands/M0104.json +100 -94
  112. data/schemas/tlc/1.0.13/commands/command_requests.json +1293 -1
  113. data/schemas/tlc/1.0.13/defs/guards.json +19 -0
  114. data/schemas/tlc/1.0.13/sxl.yaml +63 -63
  115. data/schemas/tlc/1.0.13/sxl_index.json +280 -298
  116. data/schemas/tlc/1.0.14/alarms/A0008.json +21 -15
  117. data/schemas/tlc/1.0.14/alarms/A0201.json +26 -20
  118. data/schemas/tlc/1.0.14/alarms/A0202.json +26 -20
  119. data/schemas/tlc/1.0.14/alarms/A0301.json +69 -63
  120. data/schemas/tlc/1.0.14/alarms/A0302.json +87 -81
  121. data/schemas/tlc/1.0.14/commands/M0001.json +66 -60
  122. data/schemas/tlc/1.0.14/commands/M0002.json +48 -42
  123. data/schemas/tlc/1.0.14/commands/M0003.json +48 -42
  124. data/schemas/tlc/1.0.14/commands/M0004.json +35 -29
  125. data/schemas/tlc/1.0.14/commands/M0005.json +48 -42
  126. data/schemas/tlc/1.0.14/commands/M0006.json +48 -42
  127. data/schemas/tlc/1.0.14/commands/M0007.json +35 -29
  128. data/schemas/tlc/1.0.14/commands/M0008.json +48 -42
  129. data/schemas/tlc/1.0.14/commands/M0010.json +35 -29
  130. data/schemas/tlc/1.0.14/commands/M0011.json +35 -29
  131. data/schemas/tlc/1.0.14/commands/M0012.json +35 -29
  132. data/schemas/tlc/1.0.14/commands/M0013.json +35 -29
  133. data/schemas/tlc/1.0.14/commands/M0014.json +48 -42
  134. data/schemas/tlc/1.0.14/commands/M0015.json +48 -42
  135. data/schemas/tlc/1.0.14/commands/M0016.json +35 -29
  136. data/schemas/tlc/1.0.14/commands/M0017.json +35 -29
  137. data/schemas/tlc/1.0.14/commands/M0018.json +48 -42
  138. data/schemas/tlc/1.0.14/commands/M0019.json +61 -55
  139. data/schemas/tlc/1.0.14/commands/M0103.json +51 -45
  140. data/schemas/tlc/1.0.14/commands/M0104.json +100 -94
  141. data/schemas/tlc/1.0.14/commands/command_requests.json +1293 -1
  142. data/schemas/tlc/1.0.14/defs/guards.json +19 -0
  143. data/schemas/tlc/1.0.14/sxl.yaml +63 -63
  144. data/schemas/tlc/1.0.14/sxl_index.json +304 -322
  145. data/schemas/tlc/1.0.15/alarms/A0008.json +21 -15
  146. data/schemas/tlc/1.0.15/alarms/A0201.json +26 -20
  147. data/schemas/tlc/1.0.15/alarms/A0202.json +26 -20
  148. data/schemas/tlc/1.0.15/alarms/A0301.json +69 -63
  149. data/schemas/tlc/1.0.15/alarms/A0302.json +87 -81
  150. data/schemas/tlc/1.0.15/commands/M0001.json +66 -60
  151. data/schemas/tlc/1.0.15/commands/M0002.json +48 -42
  152. data/schemas/tlc/1.0.15/commands/M0003.json +48 -42
  153. data/schemas/tlc/1.0.15/commands/M0004.json +35 -29
  154. data/schemas/tlc/1.0.15/commands/M0005.json +48 -42
  155. data/schemas/tlc/1.0.15/commands/M0006.json +48 -42
  156. data/schemas/tlc/1.0.15/commands/M0007.json +35 -29
  157. data/schemas/tlc/1.0.15/commands/M0008.json +48 -42
  158. data/schemas/tlc/1.0.15/commands/M0010.json +35 -29
  159. data/schemas/tlc/1.0.15/commands/M0011.json +35 -29
  160. data/schemas/tlc/1.0.15/commands/M0012.json +35 -29
  161. data/schemas/tlc/1.0.15/commands/M0013.json +35 -29
  162. data/schemas/tlc/1.0.15/commands/M0014.json +48 -42
  163. data/schemas/tlc/1.0.15/commands/M0015.json +48 -42
  164. data/schemas/tlc/1.0.15/commands/M0016.json +35 -29
  165. data/schemas/tlc/1.0.15/commands/M0017.json +35 -29
  166. data/schemas/tlc/1.0.15/commands/M0018.json +48 -42
  167. data/schemas/tlc/1.0.15/commands/M0019.json +61 -55
  168. data/schemas/tlc/1.0.15/commands/M0020.json +61 -55
  169. data/schemas/tlc/1.0.15/commands/M0021.json +35 -29
  170. data/schemas/tlc/1.0.15/commands/M0103.json +51 -45
  171. data/schemas/tlc/1.0.15/commands/M0104.json +100 -94
  172. data/schemas/tlc/1.0.15/commands/command_requests.json +1425 -1
  173. data/schemas/tlc/1.0.15/defs/guards.json +19 -0
  174. data/schemas/tlc/1.0.15/sxl.yaml +66 -66
  175. data/schemas/tlc/1.0.15/sxl_index.json +330 -350
  176. data/schemas/tlc/1.0.7/alarms/A0008.json +21 -15
  177. data/schemas/tlc/1.0.7/alarms/A0201.json +26 -20
  178. data/schemas/tlc/1.0.7/alarms/A0202.json +26 -20
  179. data/schemas/tlc/1.0.7/alarms/A0301.json +69 -63
  180. data/schemas/tlc/1.0.7/alarms/A0302.json +87 -81
  181. data/schemas/tlc/1.0.7/commands/M0001.json +66 -60
  182. data/schemas/tlc/1.0.7/commands/M0002.json +48 -42
  183. data/schemas/tlc/1.0.7/commands/M0003.json +48 -42
  184. data/schemas/tlc/1.0.7/commands/M0004.json +35 -29
  185. data/schemas/tlc/1.0.7/commands/M0005.json +48 -42
  186. data/schemas/tlc/1.0.7/commands/M0006.json +48 -42
  187. data/schemas/tlc/1.0.7/commands/M0007.json +35 -29
  188. data/schemas/tlc/1.0.7/commands/M0008.json +48 -42
  189. data/schemas/tlc/1.0.7/commands/M0010.json +35 -29
  190. data/schemas/tlc/1.0.7/commands/M0011.json +35 -29
  191. data/schemas/tlc/1.0.7/commands/M0019.json +61 -55
  192. data/schemas/tlc/1.0.7/commands/M0103.json +51 -45
  193. data/schemas/tlc/1.0.7/commands/M0104.json +100 -94
  194. data/schemas/tlc/1.0.7/commands/command_requests.json +895 -1
  195. data/schemas/tlc/1.0.7/defs/guards.json +19 -0
  196. data/schemas/tlc/1.0.7/sxl.yaml +58 -58
  197. data/schemas/tlc/1.0.7/sxl_index.json +228 -246
  198. data/schemas/tlc/1.0.8/alarms/A0008.json +21 -15
  199. data/schemas/tlc/1.0.8/alarms/A0201.json +26 -20
  200. data/schemas/tlc/1.0.8/alarms/A0202.json +26 -20
  201. data/schemas/tlc/1.0.8/alarms/A0301.json +69 -63
  202. data/schemas/tlc/1.0.8/alarms/A0302.json +87 -81
  203. data/schemas/tlc/1.0.8/commands/M0001.json +66 -60
  204. data/schemas/tlc/1.0.8/commands/M0002.json +48 -42
  205. data/schemas/tlc/1.0.8/commands/M0003.json +48 -42
  206. data/schemas/tlc/1.0.8/commands/M0004.json +35 -29
  207. data/schemas/tlc/1.0.8/commands/M0005.json +48 -42
  208. data/schemas/tlc/1.0.8/commands/M0006.json +48 -42
  209. data/schemas/tlc/1.0.8/commands/M0007.json +35 -29
  210. data/schemas/tlc/1.0.8/commands/M0008.json +48 -42
  211. data/schemas/tlc/1.0.8/commands/M0010.json +35 -29
  212. data/schemas/tlc/1.0.8/commands/M0011.json +35 -29
  213. data/schemas/tlc/1.0.8/commands/M0012.json +35 -29
  214. data/schemas/tlc/1.0.8/commands/M0013.json +35 -29
  215. data/schemas/tlc/1.0.8/commands/M0019.json +61 -55
  216. data/schemas/tlc/1.0.8/commands/M0103.json +51 -45
  217. data/schemas/tlc/1.0.8/commands/M0104.json +100 -94
  218. data/schemas/tlc/1.0.8/commands/command_requests.json +995 -1
  219. data/schemas/tlc/1.0.8/defs/guards.json +19 -0
  220. data/schemas/tlc/1.0.8/sxl.yaml +56 -56
  221. data/schemas/tlc/1.0.8/sxl_index.json +226 -244
  222. data/schemas/tlc/1.0.9/alarms/A0008.json +21 -15
  223. data/schemas/tlc/1.0.9/alarms/A0201.json +26 -20
  224. data/schemas/tlc/1.0.9/alarms/A0202.json +26 -20
  225. data/schemas/tlc/1.0.9/alarms/A0301.json +69 -63
  226. data/schemas/tlc/1.0.9/alarms/A0302.json +87 -81
  227. data/schemas/tlc/1.0.9/commands/M0001.json +66 -60
  228. data/schemas/tlc/1.0.9/commands/M0002.json +48 -42
  229. data/schemas/tlc/1.0.9/commands/M0003.json +48 -42
  230. data/schemas/tlc/1.0.9/commands/M0004.json +35 -29
  231. data/schemas/tlc/1.0.9/commands/M0005.json +48 -42
  232. data/schemas/tlc/1.0.9/commands/M0006.json +48 -42
  233. data/schemas/tlc/1.0.9/commands/M0007.json +35 -29
  234. data/schemas/tlc/1.0.9/commands/M0008.json +48 -42
  235. data/schemas/tlc/1.0.9/commands/M0010.json +35 -29
  236. data/schemas/tlc/1.0.9/commands/M0011.json +35 -29
  237. data/schemas/tlc/1.0.9/commands/M0012.json +35 -29
  238. data/schemas/tlc/1.0.9/commands/M0013.json +35 -29
  239. data/schemas/tlc/1.0.9/commands/M0019.json +61 -55
  240. data/schemas/tlc/1.0.9/commands/M0103.json +51 -45
  241. data/schemas/tlc/1.0.9/commands/M0104.json +100 -94
  242. data/schemas/tlc/1.0.9/commands/command_requests.json +995 -1
  243. data/schemas/tlc/1.0.9/defs/guards.json +19 -0
  244. data/schemas/tlc/1.0.9/sxl.yaml +56 -56
  245. data/schemas/tlc/1.0.9/sxl_index.json +226 -244
  246. data/schemas/tlc/1.1.0/alarms/A0007.json +25 -19
  247. data/schemas/tlc/1.1.0/alarms/A0008.json +21 -15
  248. data/schemas/tlc/1.1.0/alarms/A0201.json +26 -20
  249. data/schemas/tlc/1.1.0/alarms/A0202.json +26 -20
  250. data/schemas/tlc/1.1.0/alarms/A0301.json +69 -63
  251. data/schemas/tlc/1.1.0/alarms/A0302.json +87 -81
  252. data/schemas/tlc/1.1.0/alarms/A0303.json +69 -63
  253. data/schemas/tlc/1.1.0/alarms/A0304.json +87 -81
  254. data/schemas/tlc/1.1.0/commands/M0001.json +66 -60
  255. data/schemas/tlc/1.1.0/commands/M0002.json +48 -42
  256. data/schemas/tlc/1.1.0/commands/M0003.json +48 -42
  257. data/schemas/tlc/1.1.0/commands/M0004.json +35 -29
  258. data/schemas/tlc/1.1.0/commands/M0005.json +48 -42
  259. data/schemas/tlc/1.1.0/commands/M0006.json +48 -42
  260. data/schemas/tlc/1.1.0/commands/M0007.json +35 -29
  261. data/schemas/tlc/1.1.0/commands/M0008.json +48 -42
  262. data/schemas/tlc/1.1.0/commands/M0010.json +35 -29
  263. data/schemas/tlc/1.1.0/commands/M0011.json +35 -29
  264. data/schemas/tlc/1.1.0/commands/M0012.json +35 -29
  265. data/schemas/tlc/1.1.0/commands/M0013.json +35 -29
  266. data/schemas/tlc/1.1.0/commands/M0014.json +48 -42
  267. data/schemas/tlc/1.1.0/commands/M0015.json +48 -42
  268. data/schemas/tlc/1.1.0/commands/M0016.json +35 -29
  269. data/schemas/tlc/1.1.0/commands/M0017.json +35 -29
  270. data/schemas/tlc/1.1.0/commands/M0018.json +48 -42
  271. data/schemas/tlc/1.1.0/commands/M0019.json +61 -55
  272. data/schemas/tlc/1.1.0/commands/M0020.json +61 -55
  273. data/schemas/tlc/1.1.0/commands/M0021.json +35 -29
  274. data/schemas/tlc/1.1.0/commands/M0022.json +194 -188
  275. data/schemas/tlc/1.1.0/commands/M0023.json +35 -29
  276. data/schemas/tlc/1.1.0/commands/M0103.json +51 -45
  277. data/schemas/tlc/1.1.0/commands/M0104.json +100 -94
  278. data/schemas/tlc/1.1.0/commands/command_requests.json +1525 -1
  279. data/schemas/tlc/1.1.0/defs/guards.json +19 -0
  280. data/schemas/tlc/1.1.0/statuses/S0033.json +2 -2
  281. data/schemas/tlc/1.1.0/sxl.yaml +75 -74
  282. data/schemas/tlc/1.1.0/sxl_index.json +391 -398
  283. data/schemas/tlc/1.2.0/alarms/A0007.json +25 -19
  284. data/schemas/tlc/1.2.0/alarms/A0008.json +21 -15
  285. data/schemas/tlc/1.2.0/alarms/A0201.json +26 -20
  286. data/schemas/tlc/1.2.0/alarms/A0202.json +26 -20
  287. data/schemas/tlc/1.2.0/alarms/A0301.json +69 -63
  288. data/schemas/tlc/1.2.0/alarms/A0302.json +87 -81
  289. data/schemas/tlc/1.2.0/alarms/A0303.json +69 -63
  290. data/schemas/tlc/1.2.0/alarms/A0304.json +87 -81
  291. data/schemas/tlc/1.2.0/commands/M0001.json +66 -60
  292. data/schemas/tlc/1.2.0/commands/M0002.json +48 -42
  293. data/schemas/tlc/1.2.0/commands/M0003.json +48 -42
  294. data/schemas/tlc/1.2.0/commands/M0004.json +35 -29
  295. data/schemas/tlc/1.2.0/commands/M0005.json +48 -42
  296. data/schemas/tlc/1.2.0/commands/M0006.json +48 -42
  297. data/schemas/tlc/1.2.0/commands/M0007.json +35 -29
  298. data/schemas/tlc/1.2.0/commands/M0008.json +48 -42
  299. data/schemas/tlc/1.2.0/commands/M0010.json +35 -29
  300. data/schemas/tlc/1.2.0/commands/M0011.json +35 -29
  301. data/schemas/tlc/1.2.0/commands/M0012.json +35 -29
  302. data/schemas/tlc/1.2.0/commands/M0013.json +35 -29
  303. data/schemas/tlc/1.2.0/commands/M0014.json +48 -42
  304. data/schemas/tlc/1.2.0/commands/M0015.json +48 -42
  305. data/schemas/tlc/1.2.0/commands/M0016.json +35 -29
  306. data/schemas/tlc/1.2.0/commands/M0017.json +35 -29
  307. data/schemas/tlc/1.2.0/commands/M0018.json +48 -42
  308. data/schemas/tlc/1.2.0/commands/M0019.json +61 -55
  309. data/schemas/tlc/1.2.0/commands/M0020.json +61 -55
  310. data/schemas/tlc/1.2.0/commands/M0021.json +35 -29
  311. data/schemas/tlc/1.2.0/commands/M0022.json +194 -188
  312. data/schemas/tlc/1.2.0/commands/M0023.json +35 -29
  313. data/schemas/tlc/1.2.0/commands/M0103.json +51 -45
  314. data/schemas/tlc/1.2.0/commands/M0104.json +100 -94
  315. data/schemas/tlc/1.2.0/commands/command_requests.json +1525 -1
  316. data/schemas/tlc/1.2.0/defs/guards.json +19 -0
  317. data/schemas/tlc/1.2.0/statuses/S0033.json +2 -2
  318. data/schemas/tlc/1.2.0/sxl.yaml +77 -76
  319. data/schemas/tlc/1.2.0/sxl_index.json +401 -397
  320. data/schemas/tlc/1.2.1/alarms/A0007.json +25 -19
  321. data/schemas/tlc/1.2.1/alarms/A0008.json +21 -15
  322. data/schemas/tlc/1.2.1/alarms/A0201.json +26 -20
  323. data/schemas/tlc/1.2.1/alarms/A0202.json +26 -20
  324. data/schemas/tlc/1.2.1/alarms/A0301.json +69 -63
  325. data/schemas/tlc/1.2.1/alarms/A0302.json +87 -81
  326. data/schemas/tlc/1.2.1/alarms/A0303.json +69 -63
  327. data/schemas/tlc/1.2.1/alarms/A0304.json +87 -81
  328. data/schemas/tlc/1.2.1/commands/M0001.json +66 -60
  329. data/schemas/tlc/1.2.1/commands/M0002.json +48 -42
  330. data/schemas/tlc/1.2.1/commands/M0003.json +48 -42
  331. data/schemas/tlc/1.2.1/commands/M0004.json +35 -29
  332. data/schemas/tlc/1.2.1/commands/M0005.json +48 -42
  333. data/schemas/tlc/1.2.1/commands/M0006.json +48 -42
  334. data/schemas/tlc/1.2.1/commands/M0007.json +35 -29
  335. data/schemas/tlc/1.2.1/commands/M0008.json +48 -42
  336. data/schemas/tlc/1.2.1/commands/M0010.json +35 -29
  337. data/schemas/tlc/1.2.1/commands/M0011.json +35 -29
  338. data/schemas/tlc/1.2.1/commands/M0012.json +35 -29
  339. data/schemas/tlc/1.2.1/commands/M0013.json +35 -29
  340. data/schemas/tlc/1.2.1/commands/M0014.json +48 -42
  341. data/schemas/tlc/1.2.1/commands/M0015.json +48 -42
  342. data/schemas/tlc/1.2.1/commands/M0016.json +35 -29
  343. data/schemas/tlc/1.2.1/commands/M0017.json +35 -29
  344. data/schemas/tlc/1.2.1/commands/M0018.json +48 -42
  345. data/schemas/tlc/1.2.1/commands/M0019.json +61 -55
  346. data/schemas/tlc/1.2.1/commands/M0020.json +61 -55
  347. data/schemas/tlc/1.2.1/commands/M0021.json +35 -29
  348. data/schemas/tlc/1.2.1/commands/M0022.json +194 -188
  349. data/schemas/tlc/1.2.1/commands/M0023.json +35 -29
  350. data/schemas/tlc/1.2.1/commands/M0103.json +51 -45
  351. data/schemas/tlc/1.2.1/commands/M0104.json +100 -94
  352. data/schemas/tlc/1.2.1/commands/command_requests.json +1525 -1
  353. data/schemas/tlc/1.2.1/defs/guards.json +19 -0
  354. data/schemas/tlc/1.2.1/statuses/S0033.json +2 -2
  355. data/schemas/tlc/1.2.1/sxl.yaml +77 -76
  356. data/schemas/tlc/1.2.1/sxl_index.json +401 -397
  357. data/schemas/tlc/1.3.0/alarms/A0007.json +25 -19
  358. data/schemas/tlc/1.3.0/alarms/A0008.json +21 -15
  359. data/schemas/tlc/1.3.0/alarms/A0201.json +26 -20
  360. data/schemas/tlc/1.3.0/alarms/A0202.json +26 -20
  361. data/schemas/tlc/1.3.0/alarms/A0301.json +69 -63
  362. data/schemas/tlc/1.3.0/alarms/A0302.json +87 -81
  363. data/schemas/tlc/1.3.0/alarms/A0303.json +70 -64
  364. data/schemas/tlc/1.3.0/alarms/A0304.json +88 -82
  365. data/schemas/tlc/1.3.0/commands/M0001.json +66 -60
  366. data/schemas/tlc/1.3.0/commands/M0002.json +48 -42
  367. data/schemas/tlc/1.3.0/commands/M0003.json +48 -42
  368. data/schemas/tlc/1.3.0/commands/M0004.json +35 -29
  369. data/schemas/tlc/1.3.0/commands/M0005.json +48 -42
  370. data/schemas/tlc/1.3.0/commands/M0006.json +48 -42
  371. data/schemas/tlc/1.3.0/commands/M0007.json +35 -29
  372. data/schemas/tlc/1.3.0/commands/M0008.json +61 -55
  373. data/schemas/tlc/1.3.0/commands/M0010.json +35 -29
  374. data/schemas/tlc/1.3.0/commands/M0011.json +35 -29
  375. data/schemas/tlc/1.3.0/commands/M0012.json +35 -29
  376. data/schemas/tlc/1.3.0/commands/M0013.json +36 -30
  377. data/schemas/tlc/1.3.0/commands/M0014.json +48 -42
  378. data/schemas/tlc/1.3.0/commands/M0015.json +48 -42
  379. data/schemas/tlc/1.3.0/commands/M0016.json +35 -29
  380. data/schemas/tlc/1.3.0/commands/M0017.json +35 -29
  381. data/schemas/tlc/1.3.0/commands/M0018.json +48 -42
  382. data/schemas/tlc/1.3.0/commands/M0019.json +61 -55
  383. data/schemas/tlc/1.3.0/commands/M0020.json +61 -55
  384. data/schemas/tlc/1.3.0/commands/M0021.json +35 -29
  385. data/schemas/tlc/1.3.0/commands/M0022.json +195 -189
  386. data/schemas/tlc/1.3.0/commands/M0023.json +35 -29
  387. data/schemas/tlc/1.3.0/commands/M0024.json +21 -15
  388. data/schemas/tlc/1.3.0/commands/M0103.json +51 -45
  389. data/schemas/tlc/1.3.0/commands/M0104.json +100 -94
  390. data/schemas/tlc/1.3.0/commands/command_requests.json +1559 -1
  391. data/schemas/tlc/1.3.0/defs/guards.json +19 -0
  392. data/schemas/tlc/1.3.0/statuses/S0001.json +4 -4
  393. data/schemas/tlc/1.3.0/statuses/S0005.json +3 -3
  394. data/schemas/tlc/1.3.0/statuses/S0006.json +2 -2
  395. data/schemas/tlc/1.3.0/statuses/S0007.json +1 -1
  396. data/schemas/tlc/1.3.0/statuses/S0008.json +1 -1
  397. data/schemas/tlc/1.3.0/statuses/S0009.json +1 -1
  398. data/schemas/tlc/1.3.0/statuses/S0010.json +1 -1
  399. data/schemas/tlc/1.3.0/statuses/S0011.json +1 -1
  400. data/schemas/tlc/1.3.0/statuses/S0012.json +1 -1
  401. data/schemas/tlc/1.3.0/statuses/S0013.json +1 -1
  402. data/schemas/tlc/1.3.0/statuses/S0014.json +1 -1
  403. data/schemas/tlc/1.3.0/statuses/S0015.json +1 -1
  404. data/schemas/tlc/1.3.0/statuses/S0016.json +1 -1
  405. data/schemas/tlc/1.3.0/statuses/S0017.json +1 -1
  406. data/schemas/tlc/1.3.0/statuses/S0019.json +1 -1
  407. data/schemas/tlc/1.3.0/statuses/S0020.json +1 -1
  408. data/schemas/tlc/1.3.0/statuses/S0025.json +2 -2
  409. data/schemas/tlc/1.3.0/statuses/S0027.json +1 -1
  410. data/schemas/tlc/1.3.0/statuses/S0032.json +2 -2
  411. data/schemas/tlc/1.3.0/statuses/S0033.json +5 -5
  412. data/schemas/tlc/1.3.0/statuses/S0034.json +1 -1
  413. data/schemas/tlc/1.3.0/statuses/S0035.json +1 -1
  414. data/schemas/tlc/1.3.0/statuses/S0091.json +1 -1
  415. data/schemas/tlc/1.3.0/statuses/S0092.json +1 -1
  416. data/schemas/tlc/1.3.0/statuses/S0096.json +6 -6
  417. data/schemas/tlc/1.3.0/statuses/S0201.json +1 -1
  418. data/schemas/tlc/1.3.0/statuses/S0202.json +1 -1
  419. data/schemas/tlc/1.3.0/statuses/S0203.json +1 -1
  420. data/schemas/tlc/1.3.0/statuses/S0204.json +9 -9
  421. data/schemas/tlc/1.3.0/statuses/S0205.json +1 -1
  422. data/schemas/tlc/1.3.0/statuses/S0206.json +1 -1
  423. data/schemas/tlc/1.3.0/statuses/S0207.json +1 -1
  424. data/schemas/tlc/1.3.0/statuses/S0208.json +9 -9
  425. data/schemas/tlc/1.3.0/sxl_index.json +408 -402
  426. metadata +8 -1
@@ -3,23 +3,30 @@ module RSMP
3
3
  module Modules
4
4
  # Status request and subscription handling
5
5
  module Status
6
+ include StatusUpdates
7
+
6
8
  def rsmpify_value(value, quality)
7
- if value.is_a?(Array) || value.is_a?(Set)
8
- value
9
- elsif %w[undefined unknown].include?(quality.to_s)
9
+ if %w[undefined unknown].include?(quality.to_s)
10
10
  nil
11
11
  else
12
- value.to_s
12
+ value
13
13
  end
14
14
  end
15
15
 
16
16
  def fetch_status_values(component, args)
17
17
  args.map do |arg|
18
- value, quality = component.get_status arg['sCI'], arg['n'], { sxl_version: sxl_version }
19
- { 's' => rsmpify_value(value, quality), 'q' => quality.to_s }.merge arg
18
+ fetch_status_value component, arg
20
19
  end
21
20
  end
22
21
 
22
+ def fetch_status_value(component, arg)
23
+ value, quality = component.get_status arg['sCI'], arg['n'], { sxl_version: sxl_version }
24
+ { 's' => rsmpify_value(value, quality), 'q' => quality.to_s }.merge arg
25
+ rescue UnknownStatus => e
26
+ log e.to_s, level: :warning
27
+ { 's' => nil, 'q' => 'unknown' }.merge arg
28
+ end
29
+
23
30
  def build_undefined_statuses(args)
24
31
  args.map { |arg| arg.dup.merge('q' => 'undefined', 's' => nil) }
25
32
  end
@@ -115,104 +122,6 @@ module RSMP
115
122
  @status_subscriptions.delete(component_id) if by_code.empty?
116
123
  end
117
124
  end
118
-
119
- def fetch_last_sent_status(component, code, name)
120
- @last_status_sent&.dig component, code, name
121
- end
122
-
123
- def store_last_sent_status(message)
124
- component_id = message.attribute('cId')
125
- @last_status_sent ||= {}
126
- @last_status_sent[component_id] ||= {}
127
- message.attribute('sS').each do |item|
128
- sci = item['sCI']
129
- n = item['n']
130
- s = item['s']
131
- @last_status_sent[component_id][sci] ||= {}
132
- @last_status_sent[component_id][sci][n] = s
133
- end
134
- end
135
-
136
- def check_on_change_update(subscription, component, code, name)
137
- return [nil, false] unless subscription[:interval].zero?
138
-
139
- current = nil
140
- if component
141
- current, quality = *(component.get_status code, name)
142
- current = rsmpify_value(current, quality)
143
- end
144
- last_sent = fetch_last_sent_status component.c_id, code, name
145
- [current, current != last_sent]
146
- end
147
-
148
- def interval_update_due?(subscription, now)
149
- return true if subscription[:last_sent_at].nil?
150
-
151
- (now - subscription[:last_sent_at]) >= subscription[:interval]
152
- end
153
-
154
- def check_status_subscription(subscription, component, code, name, now)
155
- current, should_send = check_on_change_update(subscription, component, code, name)
156
- should_send ||= interval_update_due?(subscription, now) if subscription[:interval].positive?
157
- return [nil, false] unless should_send
158
-
159
- subscription[:last_sent_at] = now
160
- [current, true]
161
- end
162
-
163
- def status_update_timer(now)
164
- update_list = {}
165
-
166
- @status_subscriptions.each_pair do |component_id, by_code|
167
- component = @site.find_component component_id
168
- by_code.each_pair do |code, by_name|
169
- by_name.each_pair do |name, subscription|
170
- current, should_send = check_status_subscription(subscription, component, code, name, now)
171
- next unless should_send
172
-
173
- update_list[component_id] ||= {}
174
- update_list[component_id][code] ||= {}
175
- update_list[component_id][code][name] = current
176
- end
177
- end
178
- end
179
- send_status_updates update_list
180
- end
181
-
182
- def build_status_list(component, by_code)
183
- ss = []
184
- by_code.each_pair do |code, names|
185
- names.map do |status_name, value|
186
- if value
187
- quality = 'recent'
188
- else
189
- value, quality = component.get_status code, status_name
190
- end
191
- ss << { 'sCI' => code,
192
- 'n' => status_name,
193
- 's' => rsmpify_value(value, quality),
194
- 'q' => quality }
195
- end
196
- end
197
- ss
198
- end
199
-
200
- def send_status_updates(update_list)
201
- now = clock.to_s
202
- update_list.each_pair do |component_id, by_code|
203
- component = @site.find_component component_id
204
- ss = build_status_list(component, by_code)
205
- update = StatusUpdate.new({
206
- 'cId' => component_id,
207
- 'sTs' => now,
208
- 'sS' => ss
209
- })
210
- apply_nts_message_attributes update
211
- send_message update
212
- store_last_sent_status update
213
- component.status_updates_sent
214
- end
215
- end
216
125
  end
217
126
  end
218
127
  end
@@ -0,0 +1,148 @@
1
+ module RSMP
2
+ class SupervisorProxy < Proxy
3
+ module Modules
4
+ # Periodic and on-change status update handling.
5
+ module StatusUpdates
6
+ PrecomputedStatusValue = Struct.new(:value)
7
+
8
+ def fetch_last_sent_status(component, code, name)
9
+ @last_status_sent&.dig component, code, name
10
+ end
11
+
12
+ def store_last_sent_status(message)
13
+ component_id = message.attribute('cId')
14
+ @last_status_sent ||= {}
15
+ @last_status_sent[component_id] ||= {}
16
+ message.attribute('sS').each { |item| store_last_sent_status_item(component_id, item) }
17
+ end
18
+
19
+ def store_last_sent_status_item(component_id, item)
20
+ @last_status_sent[component_id][item['sCI']] ||= {}
21
+ @last_status_sent[component_id][item['sCI']][item['n']] = item['s']
22
+ end
23
+
24
+ def check_on_change_update(subscription, component, code, name)
25
+ return [nil, false] unless subscription[:interval].zero?
26
+
27
+ current = current_status_value(component, code, name)
28
+ last_sent = fetch_last_sent_status component.c_id, code, name
29
+ [current, encode_status_value(code, name, current) != last_sent]
30
+ end
31
+
32
+ def current_status_value(component, code, name)
33
+ return unless component
34
+
35
+ value, quality = *(component.get_status code, name)
36
+ rsmpify_value(value, quality)
37
+ end
38
+
39
+ def encode_status_value(code, name, value)
40
+ message = { 'type' => 'StatusUpdate', 'sS' => [{ 'sCI' => code, 'n' => name }] }
41
+ type, version = RSMP::Schema.resolve_sxl(message, schemas: schemas)
42
+ descriptor = RSMP::Schema.sxl_argument_descriptor(type, version, :statuses, code, name)
43
+ descriptor ? RSMP::Message.encode_sxl_value(value, descriptor) : value
44
+ end
45
+
46
+ def interval_update_due?(subscription, now)
47
+ return true if subscription[:last_sent_at].nil?
48
+
49
+ (now - subscription[:last_sent_at]) >= subscription[:interval]
50
+ end
51
+
52
+ def check_status_subscription(subscription, component, code, name, now)
53
+ current, should_send = check_on_change_update(subscription, component, code, name)
54
+ should_send ||= interval_update_due?(subscription, now) if subscription[:interval].positive?
55
+ return [nil, false] unless should_send
56
+
57
+ subscription[:last_sent_at] = now
58
+ [current, true]
59
+ end
60
+
61
+ def status_update_timer(now)
62
+ send_status_updates status_updates_due(now)
63
+ end
64
+
65
+ def status_updates_due(now)
66
+ update_list = {}
67
+ @status_subscriptions.each_pair do |component_id, by_code|
68
+ collect_component_status_updates(update_list, component_id, by_code, now)
69
+ end
70
+ update_list
71
+ end
72
+
73
+ def collect_component_status_updates(update_list, component_id, by_code, now)
74
+ component = @site.find_component component_id
75
+ by_code.each_pair do |code, by_name|
76
+ by_name.each_pair do |name, subscription|
77
+ current, should_send = check_status_subscription(subscription, component, code, name, now)
78
+ next unless should_send
79
+
80
+ value = precomputed_status_value(subscription, current)
81
+ add_status_update(update_list, component.c_id, code, name, value)
82
+ end
83
+ end
84
+ end
85
+
86
+ def add_status_update(update_list, component_id, code, name, value)
87
+ update_list[component_id] ||= {}
88
+ update_list[component_id][code] ||= {}
89
+ update_list[component_id][code][name] = value
90
+ end
91
+
92
+ def precomputed_status_value(subscription, current)
93
+ PrecomputedStatusValue.new(current) if subscription[:interval].zero?
94
+ end
95
+
96
+ def build_status_list(component, by_code)
97
+ by_code.each_pair.with_object([]) do |(code, names), ss|
98
+ each_status_name(names) do |status_name, value|
99
+ ss << build_status_item(component, code, status_name, value)
100
+ end
101
+ end
102
+ end
103
+
104
+ def each_status_name(names, &block)
105
+ if names.respond_to?(:each_pair)
106
+ names.each_pair(&block)
107
+ else
108
+ names.each { |status_name| block.call(status_name, nil) }
109
+ end
110
+ end
111
+
112
+ def build_status_item(component, code, status_name, value)
113
+ value, quality = status_item_value(component, code, status_name, value)
114
+ { 'sCI' => code, 'n' => status_name, 's' => rsmpify_value(value, quality), 'q' => quality }
115
+ end
116
+
117
+ def status_item_value(component, code, status_name, value)
118
+ return [value.value, 'recent'] if value.is_a?(PrecomputedStatusValue)
119
+
120
+ component.get_status code, status_name
121
+ rescue UnknownStatus => e
122
+ log e.to_s, level: :warning
123
+ [nil, 'unknown']
124
+ end
125
+
126
+ def send_status_updates(update_list)
127
+ now = clock.to_s
128
+ update_list.each_pair do |component_id, by_code|
129
+ send_component_status_update(component_id, by_code, now)
130
+ end
131
+ end
132
+
133
+ def send_component_status_update(component_id, by_code, now)
134
+ component = @site.find_component component_id
135
+ update = StatusUpdate.new({
136
+ 'cId' => component_id,
137
+ 'sTs' => now,
138
+ 'sS' => build_status_list(component, by_code)
139
+ })
140
+ apply_nts_message_attributes update
141
+ send_message update
142
+ store_last_sent_status update
143
+ component.status_updates_sent
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -28,6 +28,11 @@ module RSMP
28
28
  # handle communication
29
29
  # if disconnected, then try to reconnect
30
30
  def run
31
+ if @protocol
32
+ run_accepted_connection
33
+ return
34
+ end
35
+
31
36
  loop do
32
37
  connect
33
38
  start_reader
@@ -49,6 +54,20 @@ module RSMP
49
54
  end
50
55
  end
51
56
 
57
+ def run_accepted_connection
58
+ self.state = :connected
59
+ start_reader
60
+ start_handshake
61
+ wait_for_reader
62
+ rescue RSMP::ConnectionError => e
63
+ log e, level: :error
64
+ rescue StandardError => e
65
+ distribute_error e, level: :internal
66
+ ensure
67
+ close
68
+ stop_subtasks
69
+ end
70
+
52
71
  def start_handshake
53
72
  send_version_request @site_settings['site_id'], core_versions
54
73
  end
data/lib/rsmp/schema.rb CHANGED
@@ -218,7 +218,44 @@ module RSMP
218
218
  # raises an error if the schema type/version is not found, or has no status catalogue
219
219
  def self.status_catalogue(type, version)
220
220
  sxl_catalogue(type, version, :statuses).transform_keys(&:to_sym).transform_values do |status|
221
- status.fetch('arguments', []).map(&:to_sym)
221
+ (argument_names(status['required']) + argument_names(status['optional'])).sort.map(&:to_sym)
222
+ end
223
+ end
224
+
225
+ def self.argument_names(arguments)
226
+ case arguments
227
+ when Hash
228
+ arguments.keys
229
+ when Array
230
+ arguments
231
+ else
232
+ []
233
+ end
234
+ end
235
+
236
+ def self.sxl_catalogue_item(type, version, kind, code, options = {})
237
+ version = sanitize_version(version.to_s) if options[:lenient]
238
+ catalogue = sxl_catalogue(type, version, kind)
239
+ prefix = sxl_prefix(type, version, options)
240
+ code = code.to_s
241
+ unprefixed = prefix && code.start_with?(prefix) ? code[prefix.length..] : code
242
+ catalogue[code] || catalogue[code.to_sym] ||
243
+ catalogue[unprefixed] || catalogue[unprefixed.to_sym]
244
+ end
245
+
246
+ def self.sxl_argument_descriptor(type, version, kind, code, name)
247
+ item = sxl_catalogue_item(type, version, kind, code)
248
+ return unless item
249
+
250
+ argument_descriptor(item['required'], name) || argument_descriptor(item['optional'], name)
251
+ end
252
+
253
+ def self.argument_descriptor(arguments, name)
254
+ return unless arguments
255
+
256
+ case arguments
257
+ when Hash
258
+ arguments[name] || arguments[name.to_sym]
222
259
  end
223
260
  end
224
261
 
@@ -66,8 +66,8 @@ module RSMP
66
66
 
67
67
  def handle_m0008(arg, _options = {})
68
68
  @node.verify_security_code 2, arg['securityCode']
69
- status = arg['status'] == 'True'
70
- mode = arg['mode'] == 'True'
69
+ status = arg['status']
70
+ mode = arg['mode']
71
71
  force_detector_logic status, mode
72
72
  arg
73
73
  end
@@ -10,28 +10,6 @@ module RSMP
10
10
  plan
11
11
  end
12
12
 
13
- def string_to_bool(bool_str)
14
- case bool_str
15
- when 'True'
16
- true
17
- when 'False'
18
- false
19
- else
20
- raise RSMP::MessageRejected, "Invalid boolean '#{bool}', must be 'True' or 'False'"
21
- end
22
- end
23
-
24
- def bool_string_to_digit(bool)
25
- case bool
26
- when 'True'
27
- '1'
28
- when 'False'
29
- '0'
30
- else
31
- raise RSMP::MessageRejected, "Invalid boolean '#{bool}', must be 'True' or 'False'"
32
- end
33
- end
34
-
35
13
  def bool_to_digit(bool)
36
14
  bool ? '1' : '0'
37
15
  end
@@ -43,7 +43,7 @@ module RSMP
43
43
  def handle_m0006(arg, _options = {})
44
44
  @node.verify_security_code 2, arg['securityCode']
45
45
  input = arg['input'].to_i
46
- status = string_to_bool arg['status']
46
+ status = arg['status']
47
47
  raise MessageRejected, "Input must be in the range 1-#{@inputs.size}" unless input.between?(1, @inputs.size)
48
48
 
49
49
  if status
@@ -72,6 +72,7 @@ module RSMP
72
72
  def parse_input_status(status_string)
73
73
  set = []
74
74
  clear = []
75
+ status_string = status_string.join(',') if status_string.is_a?(Array)
75
76
  status_string.split(';').each do |part|
76
77
  offset, set_bits, clear_bits = part.split(',').map(&:to_i)
77
78
  extract_input_bits(set_bits, offset, set)
@@ -136,8 +137,8 @@ module RSMP
136
137
  def handle_m0019(arg, _options = {})
137
138
  @node.verify_security_code 2, arg['securityCode']
138
139
  input = arg['input'].to_i
139
- force = string_to_bool arg['status']
140
- forced_value = string_to_bool arg['inputValue']
140
+ force = arg['status']
141
+ forced_value = arg['inputValue']
141
142
  raise MessageRejected, "Input must be in the range 1-#{@inputs.size}" unless input.between?(1, @inputs.size)
142
143
 
143
144
  if force
@@ -74,7 +74,7 @@ module RSMP
74
74
  def handle_m0005(arg, _options = {})
75
75
  @node.verify_security_code 2, arg['securityCode']
76
76
  route = arg['emergencyroute'].to_i
77
- enable = (arg['status'] == 'True')
77
+ enable = arg['status']
78
78
  @last_emergency_route = route
79
79
 
80
80
  if enable
@@ -144,7 +144,7 @@ module RSMP
144
144
  when 'intersection'
145
145
  TrafficControllerSite.make_status @intersection
146
146
  when 'status'
147
- TrafficControllerSite.make_status TrafficControllerSite.to_rmsp_bool(@function_position == 'YellowFlash')
147
+ TrafficControllerSite.make_status @function_position == 'YellowFlash'
148
148
  when 'source'
149
149
  TrafficControllerSite.make_status @function_position_source
150
150
  end
@@ -14,7 +14,7 @@ module RSMP
14
14
  # M0002 - Set current time plan
15
15
  def handle_m0002(arg, _options = {})
16
16
  @node.verify_security_code 2, arg['securityCode']
17
- if TrafficControllerSite.from_rsmp_bool?(arg['status'])
17
+ if arg['status']
18
18
  switch_plan arg['timeplan'], source: 'forced'
19
19
  else
20
20
  switch_plan 0, source: 'startup' # TODO: use clock/calender
@@ -55,7 +55,7 @@ module RSMP
55
55
  def handle_m0014(arg, _options = {})
56
56
  @node.verify_security_code 2, arg['securityCode']
57
57
  plan = find_plan arg['plan']
58
- arg['status'].split(',').each do |item|
58
+ status_items(arg['status']).each do |item|
59
59
  matched = /(\d+)-(\d+)/.match item
60
60
  band = matched[1].to_i
61
61
  value = matched[2].to_i
@@ -77,7 +77,7 @@ module RSMP
77
77
  # M0017 - Set time tables
78
78
  def handle_m0017(arg, _options = {})
79
79
  @node.verify_security_code 2, arg['securityCode']
80
- arg['status'].split(',').each do |item|
80
+ status_items(arg['status']).each do |item|
81
81
  elems = item.split('-')
82
82
  nr = elems[0].to_i
83
83
  plan = elems[1].to_i
@@ -119,6 +119,10 @@ module RSMP
119
119
  @dynamic_bands_timeout = timeout
120
120
  end
121
121
 
122
+ def status_items(status)
123
+ status.is_a?(Array) ? status : status.split(',')
124
+ end
125
+
122
126
  # S0014 - Current signal program
123
127
  def handle_s0014(_status_code, status_name = nil, _options = {})
124
128
  case status_name
@@ -48,7 +48,7 @@ module RSMP
48
48
  TrafficControllerSite.make_status([
49
49
  {
50
50
  'intersection' => '1',
51
- 'startup' => TrafficControllerSite.to_rmsp_bool(@is_starting)
51
+ 'startup' => @is_starting
52
52
  }
53
53
  ])
54
54
  end
@@ -23,13 +23,12 @@ module RSMP
23
23
  raise 'TLC main component not found' unless main
24
24
 
25
25
  security_code = security_code_for(2)
26
- active_str = active ? 'True' : 'False'
27
26
 
28
27
  command_list = [{
29
28
  'cCI' => 'M0005',
30
29
  'cO' => 'setEmergency',
31
30
  'n' => 'status',
32
- 'v' => active_str
31
+ 'v' => command_value('M0005', 'status', active)
33
32
  }, {
34
33
  'cCI' => 'M0005',
35
34
  'cO' => 'setEmergency',
@@ -39,7 +38,7 @@ module RSMP
39
38
  'cCI' => 'M0005',
40
39
  'cO' => 'setEmergency',
41
40
  'n' => 'emergencyroute',
42
- 'v' => route.to_s
41
+ 'v' => command_value('M0005', 'emergencyroute', route)
43
42
  }]
44
43
 
45
44
  send_command_and_collect(command_list, within: within).ok!
@@ -56,7 +55,7 @@ module RSMP
56
55
  'cCI' => 'M0007',
57
56
  'cO' => 'setFixedTime',
58
57
  'n' => 'status',
59
- 'v' => status.to_s
58
+ 'v' => command_value('M0007', 'status', status)
60
59
  }, {
61
60
  'cCI' => 'M0007',
62
61
  'cO' => 'setFixedTime',
@@ -64,8 +63,7 @@ module RSMP
64
63
  'v' => security_code.to_s
65
64
  }]
66
65
 
67
- confirm_status = [{ 'sCI' => 'S0009', 'n' => 'status',
68
- 's' => /^#{Regexp.escape(status.to_s)}(,#{Regexp.escape(status.to_s)})*$/ }]
66
+ confirm_status = [{ 'sCI' => 'S0009', 'n' => 'status', 's' => [boolean_value(status)] }]
69
67
  send_command_and_collect(command_list, within: within).ok!
70
68
  wait_for_status "fixed time #{status}", confirm_status, timeout: within
71
69
  end
@@ -81,7 +79,7 @@ module RSMP
81
79
  'cCI' => 'M0003',
82
80
  'cO' => 'setTrafficSituation',
83
81
  'n' => 'status',
84
- 'v' => 'True'
82
+ 'v' => command_value('M0003', 'status', true)
85
83
  }, {
86
84
  'cCI' => 'M0003',
87
85
  'cO' => 'setTrafficSituation',
@@ -91,10 +89,10 @@ module RSMP
91
89
  'cCI' => 'M0003',
92
90
  'cO' => 'setTrafficSituation',
93
91
  'n' => 'traficsituation',
94
- 'v' => situation.to_s
92
+ 'v' => command_value('M0003', 'traficsituation', situation)
95
93
  }]
96
94
 
97
- confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => situation.to_s }]
95
+ confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => integer_value(situation) }]
98
96
  send_command_and_collect(command_list, within: within).ok!
99
97
  wait_for_status "traffic situation #{situation}", confirm_status, timeout: within
100
98
  end
@@ -110,7 +108,7 @@ module RSMP
110
108
  'cCI' => 'M0003',
111
109
  'cO' => 'setTrafficSituation',
112
110
  'n' => 'status',
113
- 'v' => 'False'
111
+ 'v' => command_value('M0003', 'status', false)
114
112
  }, {
115
113
  'cCI' => 'M0003',
116
114
  'cO' => 'setTrafficSituation',
@@ -120,10 +118,10 @@ module RSMP
120
118
  'cCI' => 'M0003',
121
119
  'cO' => 'setTrafficSituation',
122
120
  'n' => 'traficsituation',
123
- 'v' => '1'
121
+ 'v' => command_value('M0003', 'traficsituation', 1)
124
122
  }]
125
123
 
126
- confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => '1' }]
124
+ confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => 1 }]
127
125
  send_command_and_collect(command_list, within: within).ok!
128
126
  wait_for_status 'traffic situation unset', confirm_status, timeout: within
129
127
  end
@@ -135,22 +133,24 @@ module RSMP
135
133
  [
136
134
  { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'status', 'v' => status.to_s },
137
135
  { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'securityCode', 'v' => security_code.to_s },
138
- { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'timeout', 'v' => timeout_minutes.to_s },
139
- { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'intersection', 'v' => '0' }
136
+ { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'timeout',
137
+ 'v' => command_value('M0001', 'timeout', timeout_minutes) },
138
+ { 'cCI' => 'M0001', 'cO' => 'setValue', 'n' => 'intersection',
139
+ 'v' => command_value('M0001', 'intersection', 0) }
140
140
  ]
141
141
  end
142
142
 
143
143
  def functional_position_confirm_status(status)
144
144
  case status.to_s
145
145
  when 'YellowFlash'
146
- [{ 'sCI' => 'S0011', 'n' => 'status', 's' => /^True(,True)*$/ }]
146
+ [{ 'sCI' => 'S0011', 'n' => 'status', 's' => [true] }]
147
147
  when 'Dark'
148
- [{ 'sCI' => 'S0007', 'n' => 'status', 's' => /^False(,False)*$/ }]
148
+ [{ 'sCI' => 'S0007', 'n' => 'status', 's' => [false] }]
149
149
  when 'NormalControl'
150
150
  [
151
- { 'sCI' => 'S0007', 'n' => 'status', 's' => /^True(,True)*$/ },
152
- { 'sCI' => 'S0011', 'n' => 'status', 's' => /^False(,False)*$/ },
153
- { 'sCI' => 'S0005', 'n' => 'status', 's' => 'False' }
151
+ { 'sCI' => 'S0007', 'n' => 'status', 's' => [true] },
152
+ { 'sCI' => 'S0011', 'n' => 'status', 's' => [false] },
153
+ { 'sCI' => 'S0005', 'n' => 'status', 's' => false }
154
154
  ]
155
155
  else
156
156
  []
@@ -15,7 +15,7 @@ module RSMP
15
15
  'cCI' => 'M0008',
16
16
  'cO' => 'setForceDetectorLogic',
17
17
  'n' => 'status',
18
- 'v' => status.to_s
18
+ 'v' => command_value('M0008', 'status', status)
19
19
  }, {
20
20
  'cCI' => 'M0008',
21
21
  'cO' => 'setForceDetectorLogic',
@@ -25,7 +25,7 @@ module RSMP
25
25
  'cCI' => 'M0008',
26
26
  'cO' => 'setForceDetectorLogic',
27
27
  'n' => 'mode',
28
- 'v' => mode.to_s
28
+ 'v' => command_value('M0008', 'mode', mode)
29
29
  }]
30
30
  send_command_and_collect(command_list, component: component_id, within: within).ok!
31
31
  end
@@ -41,7 +41,7 @@ module RSMP
41
41
  'cCI' => 'M0021',
42
42
  'cO' => 'setLevel',
43
43
  'n' => 'status',
44
- 'v' => status.to_s
44
+ 'v' => command_value('M0021', 'status', status)
45
45
  }, {
46
46
  'cCI' => 'M0021',
47
47
  'cO' => 'setLevel',