rsmp 0.46.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 (433) 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 +14 -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 +83 -0
  10. data/lib/rsmp/cli/configuration.rb +30 -0
  11. data/lib/rsmp/cli.rb +45 -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/config.rb +63 -0
  16. data/lib/rsmp/convert/export/json_schema/index.rb +64 -0
  17. data/lib/rsmp/convert/export/json_schema/items.rb +9 -1
  18. data/lib/rsmp/convert/export/json_schema/outputs.rb +65 -25
  19. data/lib/rsmp/convert/export/json_schema/values.rb +40 -11
  20. data/lib/rsmp/convert/export/json_schema.rb +3 -1
  21. data/lib/rsmp/message/sxl_codec.rb +194 -0
  22. data/lib/rsmp/message.rb +2 -0
  23. data/lib/rsmp/node/site/connections.rb +80 -0
  24. data/lib/rsmp/node/site/site.rb +21 -35
  25. data/lib/rsmp/node/supervisor/supervisor.rb +42 -0
  26. data/lib/rsmp/options/options.rb +21 -9
  27. data/lib/rsmp/options/schemas/config_common.json +129 -0
  28. data/lib/rsmp/options/schemas/log.json +71 -0
  29. data/lib/rsmp/options/schemas/site.json +12 -57
  30. data/lib/rsmp/options/schemas/supervisor.json +4 -29
  31. data/lib/rsmp/options/schemas/supervisor_site.json +19 -31
  32. data/lib/rsmp/options/schemas/traffic_controller_site.json +1 -2
  33. data/lib/rsmp/options/site_options.rb +31 -23
  34. data/lib/rsmp/options/supervisor_options.rb +1 -0
  35. data/lib/rsmp/proxy/modules/receive.rb +3 -1
  36. data/lib/rsmp/proxy/modules/send.rb +26 -14
  37. data/lib/rsmp/proxy/proxy.rb +17 -0
  38. data/lib/rsmp/proxy/site/connection.rb +79 -0
  39. data/lib/rsmp/proxy/site/modules/commands.rb +24 -1
  40. data/lib/rsmp/proxy/site/site_proxy.rb +6 -15
  41. data/lib/rsmp/proxy/supervisor/modules/commands.rb +55 -0
  42. data/lib/rsmp/proxy/supervisor/modules/message_buffer.rb +0 -5
  43. data/lib/rsmp/proxy/supervisor/modules/status.rb +13 -104
  44. data/lib/rsmp/proxy/supervisor/modules/status_updates.rb +148 -0
  45. data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +19 -0
  46. data/lib/rsmp/schema.rb +38 -1
  47. data/lib/rsmp/tlc/detector_logic.rb +2 -2
  48. data/lib/rsmp/tlc/modules/helpers.rb +0 -22
  49. data/lib/rsmp/tlc/modules/inputs.rb +4 -3
  50. data/lib/rsmp/tlc/modules/modes.rb +2 -2
  51. data/lib/rsmp/tlc/modules/plans.rb +7 -3
  52. data/lib/rsmp/tlc/modules/system.rb +1 -1
  53. data/lib/rsmp/tlc/proxy/control.rb +19 -19
  54. data/lib/rsmp/tlc/proxy/detectors.rb +3 -3
  55. data/lib/rsmp/tlc/proxy/io.rb +15 -12
  56. data/lib/rsmp/tlc/proxy/plans.rb +14 -14
  57. data/lib/rsmp/tlc/proxy/status.rb +9 -5
  58. data/lib/rsmp/tlc/proxy/system.rb +12 -6
  59. data/lib/rsmp/tlc/signal_group.rb +2 -2
  60. data/lib/rsmp/tlc/supervisor_interface.rb +42 -0
  61. data/lib/rsmp/tlc/traffic_controller_site.rb +1 -18
  62. data/lib/rsmp/version.rb +1 -1
  63. data/lib/rsmp.rb +5 -0
  64. data/schemas/core/3.1.4/command_response.json +11 -0
  65. data/schemas/core/3.1.5/command_response.json +11 -0
  66. data/schemas/core/3.2.0/command_response.json +11 -0
  67. data/schemas/core/3.2.1/command_response.json +11 -0
  68. data/schemas/core/3.2.2/command_response.json +11 -0
  69. data/schemas/core/3.3.0/command_response.json +11 -0
  70. data/schemas/tlc/1.0.10/alarms/A0008.json +21 -15
  71. data/schemas/tlc/1.0.10/alarms/A0201.json +26 -20
  72. data/schemas/tlc/1.0.10/alarms/A0202.json +26 -20
  73. data/schemas/tlc/1.0.10/alarms/A0301.json +69 -63
  74. data/schemas/tlc/1.0.10/alarms/A0302.json +87 -81
  75. data/schemas/tlc/1.0.10/commands/M0001.json +66 -60
  76. data/schemas/tlc/1.0.10/commands/M0002.json +48 -42
  77. data/schemas/tlc/1.0.10/commands/M0003.json +48 -42
  78. data/schemas/tlc/1.0.10/commands/M0004.json +35 -29
  79. data/schemas/tlc/1.0.10/commands/M0005.json +48 -42
  80. data/schemas/tlc/1.0.10/commands/M0006.json +48 -42
  81. data/schemas/tlc/1.0.10/commands/M0007.json +35 -29
  82. data/schemas/tlc/1.0.10/commands/M0008.json +48 -42
  83. data/schemas/tlc/1.0.10/commands/M0010.json +35 -29
  84. data/schemas/tlc/1.0.10/commands/M0011.json +35 -29
  85. data/schemas/tlc/1.0.10/commands/M0012.json +35 -29
  86. data/schemas/tlc/1.0.10/commands/M0013.json +35 -29
  87. data/schemas/tlc/1.0.10/commands/M0019.json +61 -55
  88. data/schemas/tlc/1.0.10/commands/M0103.json +51 -45
  89. data/schemas/tlc/1.0.10/commands/M0104.json +100 -94
  90. data/schemas/tlc/1.0.10/commands/command_requests.json +995 -1
  91. data/schemas/tlc/1.0.10/defs/guards.json +19 -0
  92. data/schemas/tlc/1.0.10/sxl.yaml +56 -56
  93. data/schemas/tlc/1.0.10/sxl_index.json +226 -244
  94. data/schemas/tlc/1.0.13/alarms/A0008.json +21 -15
  95. data/schemas/tlc/1.0.13/alarms/A0201.json +26 -20
  96. data/schemas/tlc/1.0.13/alarms/A0202.json +26 -20
  97. data/schemas/tlc/1.0.13/alarms/A0301.json +69 -63
  98. data/schemas/tlc/1.0.13/alarms/A0302.json +87 -81
  99. data/schemas/tlc/1.0.13/commands/M0001.json +66 -60
  100. data/schemas/tlc/1.0.13/commands/M0002.json +48 -42
  101. data/schemas/tlc/1.0.13/commands/M0003.json +48 -42
  102. data/schemas/tlc/1.0.13/commands/M0004.json +35 -29
  103. data/schemas/tlc/1.0.13/commands/M0005.json +48 -42
  104. data/schemas/tlc/1.0.13/commands/M0006.json +48 -42
  105. data/schemas/tlc/1.0.13/commands/M0007.json +35 -29
  106. data/schemas/tlc/1.0.13/commands/M0008.json +48 -42
  107. data/schemas/tlc/1.0.13/commands/M0010.json +35 -29
  108. data/schemas/tlc/1.0.13/commands/M0011.json +35 -29
  109. data/schemas/tlc/1.0.13/commands/M0012.json +35 -29
  110. data/schemas/tlc/1.0.13/commands/M0013.json +35 -29
  111. data/schemas/tlc/1.0.13/commands/M0014.json +48 -42
  112. data/schemas/tlc/1.0.13/commands/M0015.json +48 -42
  113. data/schemas/tlc/1.0.13/commands/M0016.json +35 -29
  114. data/schemas/tlc/1.0.13/commands/M0017.json +35 -29
  115. data/schemas/tlc/1.0.13/commands/M0018.json +48 -42
  116. data/schemas/tlc/1.0.13/commands/M0019.json +61 -55
  117. data/schemas/tlc/1.0.13/commands/M0103.json +51 -45
  118. data/schemas/tlc/1.0.13/commands/M0104.json +100 -94
  119. data/schemas/tlc/1.0.13/commands/command_requests.json +1293 -1
  120. data/schemas/tlc/1.0.13/defs/guards.json +19 -0
  121. data/schemas/tlc/1.0.13/sxl.yaml +63 -63
  122. data/schemas/tlc/1.0.13/sxl_index.json +280 -298
  123. data/schemas/tlc/1.0.14/alarms/A0008.json +21 -15
  124. data/schemas/tlc/1.0.14/alarms/A0201.json +26 -20
  125. data/schemas/tlc/1.0.14/alarms/A0202.json +26 -20
  126. data/schemas/tlc/1.0.14/alarms/A0301.json +69 -63
  127. data/schemas/tlc/1.0.14/alarms/A0302.json +87 -81
  128. data/schemas/tlc/1.0.14/commands/M0001.json +66 -60
  129. data/schemas/tlc/1.0.14/commands/M0002.json +48 -42
  130. data/schemas/tlc/1.0.14/commands/M0003.json +48 -42
  131. data/schemas/tlc/1.0.14/commands/M0004.json +35 -29
  132. data/schemas/tlc/1.0.14/commands/M0005.json +48 -42
  133. data/schemas/tlc/1.0.14/commands/M0006.json +48 -42
  134. data/schemas/tlc/1.0.14/commands/M0007.json +35 -29
  135. data/schemas/tlc/1.0.14/commands/M0008.json +48 -42
  136. data/schemas/tlc/1.0.14/commands/M0010.json +35 -29
  137. data/schemas/tlc/1.0.14/commands/M0011.json +35 -29
  138. data/schemas/tlc/1.0.14/commands/M0012.json +35 -29
  139. data/schemas/tlc/1.0.14/commands/M0013.json +35 -29
  140. data/schemas/tlc/1.0.14/commands/M0014.json +48 -42
  141. data/schemas/tlc/1.0.14/commands/M0015.json +48 -42
  142. data/schemas/tlc/1.0.14/commands/M0016.json +35 -29
  143. data/schemas/tlc/1.0.14/commands/M0017.json +35 -29
  144. data/schemas/tlc/1.0.14/commands/M0018.json +48 -42
  145. data/schemas/tlc/1.0.14/commands/M0019.json +61 -55
  146. data/schemas/tlc/1.0.14/commands/M0103.json +51 -45
  147. data/schemas/tlc/1.0.14/commands/M0104.json +100 -94
  148. data/schemas/tlc/1.0.14/commands/command_requests.json +1293 -1
  149. data/schemas/tlc/1.0.14/defs/guards.json +19 -0
  150. data/schemas/tlc/1.0.14/sxl.yaml +63 -63
  151. data/schemas/tlc/1.0.14/sxl_index.json +304 -322
  152. data/schemas/tlc/1.0.15/alarms/A0008.json +21 -15
  153. data/schemas/tlc/1.0.15/alarms/A0201.json +26 -20
  154. data/schemas/tlc/1.0.15/alarms/A0202.json +26 -20
  155. data/schemas/tlc/1.0.15/alarms/A0301.json +69 -63
  156. data/schemas/tlc/1.0.15/alarms/A0302.json +87 -81
  157. data/schemas/tlc/1.0.15/commands/M0001.json +66 -60
  158. data/schemas/tlc/1.0.15/commands/M0002.json +48 -42
  159. data/schemas/tlc/1.0.15/commands/M0003.json +48 -42
  160. data/schemas/tlc/1.0.15/commands/M0004.json +35 -29
  161. data/schemas/tlc/1.0.15/commands/M0005.json +48 -42
  162. data/schemas/tlc/1.0.15/commands/M0006.json +48 -42
  163. data/schemas/tlc/1.0.15/commands/M0007.json +35 -29
  164. data/schemas/tlc/1.0.15/commands/M0008.json +48 -42
  165. data/schemas/tlc/1.0.15/commands/M0010.json +35 -29
  166. data/schemas/tlc/1.0.15/commands/M0011.json +35 -29
  167. data/schemas/tlc/1.0.15/commands/M0012.json +35 -29
  168. data/schemas/tlc/1.0.15/commands/M0013.json +35 -29
  169. data/schemas/tlc/1.0.15/commands/M0014.json +48 -42
  170. data/schemas/tlc/1.0.15/commands/M0015.json +48 -42
  171. data/schemas/tlc/1.0.15/commands/M0016.json +35 -29
  172. data/schemas/tlc/1.0.15/commands/M0017.json +35 -29
  173. data/schemas/tlc/1.0.15/commands/M0018.json +48 -42
  174. data/schemas/tlc/1.0.15/commands/M0019.json +61 -55
  175. data/schemas/tlc/1.0.15/commands/M0020.json +61 -55
  176. data/schemas/tlc/1.0.15/commands/M0021.json +35 -29
  177. data/schemas/tlc/1.0.15/commands/M0103.json +51 -45
  178. data/schemas/tlc/1.0.15/commands/M0104.json +100 -94
  179. data/schemas/tlc/1.0.15/commands/command_requests.json +1425 -1
  180. data/schemas/tlc/1.0.15/defs/guards.json +19 -0
  181. data/schemas/tlc/1.0.15/sxl.yaml +66 -66
  182. data/schemas/tlc/1.0.15/sxl_index.json +330 -350
  183. data/schemas/tlc/1.0.7/alarms/A0008.json +21 -15
  184. data/schemas/tlc/1.0.7/alarms/A0201.json +26 -20
  185. data/schemas/tlc/1.0.7/alarms/A0202.json +26 -20
  186. data/schemas/tlc/1.0.7/alarms/A0301.json +69 -63
  187. data/schemas/tlc/1.0.7/alarms/A0302.json +87 -81
  188. data/schemas/tlc/1.0.7/commands/M0001.json +66 -60
  189. data/schemas/tlc/1.0.7/commands/M0002.json +48 -42
  190. data/schemas/tlc/1.0.7/commands/M0003.json +48 -42
  191. data/schemas/tlc/1.0.7/commands/M0004.json +35 -29
  192. data/schemas/tlc/1.0.7/commands/M0005.json +48 -42
  193. data/schemas/tlc/1.0.7/commands/M0006.json +48 -42
  194. data/schemas/tlc/1.0.7/commands/M0007.json +35 -29
  195. data/schemas/tlc/1.0.7/commands/M0008.json +48 -42
  196. data/schemas/tlc/1.0.7/commands/M0010.json +35 -29
  197. data/schemas/tlc/1.0.7/commands/M0011.json +35 -29
  198. data/schemas/tlc/1.0.7/commands/M0019.json +61 -55
  199. data/schemas/tlc/1.0.7/commands/M0103.json +51 -45
  200. data/schemas/tlc/1.0.7/commands/M0104.json +100 -94
  201. data/schemas/tlc/1.0.7/commands/command_requests.json +895 -1
  202. data/schemas/tlc/1.0.7/defs/guards.json +19 -0
  203. data/schemas/tlc/1.0.7/sxl.yaml +58 -58
  204. data/schemas/tlc/1.0.7/sxl_index.json +228 -246
  205. data/schemas/tlc/1.0.8/alarms/A0008.json +21 -15
  206. data/schemas/tlc/1.0.8/alarms/A0201.json +26 -20
  207. data/schemas/tlc/1.0.8/alarms/A0202.json +26 -20
  208. data/schemas/tlc/1.0.8/alarms/A0301.json +69 -63
  209. data/schemas/tlc/1.0.8/alarms/A0302.json +87 -81
  210. data/schemas/tlc/1.0.8/commands/M0001.json +66 -60
  211. data/schemas/tlc/1.0.8/commands/M0002.json +48 -42
  212. data/schemas/tlc/1.0.8/commands/M0003.json +48 -42
  213. data/schemas/tlc/1.0.8/commands/M0004.json +35 -29
  214. data/schemas/tlc/1.0.8/commands/M0005.json +48 -42
  215. data/schemas/tlc/1.0.8/commands/M0006.json +48 -42
  216. data/schemas/tlc/1.0.8/commands/M0007.json +35 -29
  217. data/schemas/tlc/1.0.8/commands/M0008.json +48 -42
  218. data/schemas/tlc/1.0.8/commands/M0010.json +35 -29
  219. data/schemas/tlc/1.0.8/commands/M0011.json +35 -29
  220. data/schemas/tlc/1.0.8/commands/M0012.json +35 -29
  221. data/schemas/tlc/1.0.8/commands/M0013.json +35 -29
  222. data/schemas/tlc/1.0.8/commands/M0019.json +61 -55
  223. data/schemas/tlc/1.0.8/commands/M0103.json +51 -45
  224. data/schemas/tlc/1.0.8/commands/M0104.json +100 -94
  225. data/schemas/tlc/1.0.8/commands/command_requests.json +995 -1
  226. data/schemas/tlc/1.0.8/defs/guards.json +19 -0
  227. data/schemas/tlc/1.0.8/sxl.yaml +56 -56
  228. data/schemas/tlc/1.0.8/sxl_index.json +226 -244
  229. data/schemas/tlc/1.0.9/alarms/A0008.json +21 -15
  230. data/schemas/tlc/1.0.9/alarms/A0201.json +26 -20
  231. data/schemas/tlc/1.0.9/alarms/A0202.json +26 -20
  232. data/schemas/tlc/1.0.9/alarms/A0301.json +69 -63
  233. data/schemas/tlc/1.0.9/alarms/A0302.json +87 -81
  234. data/schemas/tlc/1.0.9/commands/M0001.json +66 -60
  235. data/schemas/tlc/1.0.9/commands/M0002.json +48 -42
  236. data/schemas/tlc/1.0.9/commands/M0003.json +48 -42
  237. data/schemas/tlc/1.0.9/commands/M0004.json +35 -29
  238. data/schemas/tlc/1.0.9/commands/M0005.json +48 -42
  239. data/schemas/tlc/1.0.9/commands/M0006.json +48 -42
  240. data/schemas/tlc/1.0.9/commands/M0007.json +35 -29
  241. data/schemas/tlc/1.0.9/commands/M0008.json +48 -42
  242. data/schemas/tlc/1.0.9/commands/M0010.json +35 -29
  243. data/schemas/tlc/1.0.9/commands/M0011.json +35 -29
  244. data/schemas/tlc/1.0.9/commands/M0012.json +35 -29
  245. data/schemas/tlc/1.0.9/commands/M0013.json +35 -29
  246. data/schemas/tlc/1.0.9/commands/M0019.json +61 -55
  247. data/schemas/tlc/1.0.9/commands/M0103.json +51 -45
  248. data/schemas/tlc/1.0.9/commands/M0104.json +100 -94
  249. data/schemas/tlc/1.0.9/commands/command_requests.json +995 -1
  250. data/schemas/tlc/1.0.9/defs/guards.json +19 -0
  251. data/schemas/tlc/1.0.9/sxl.yaml +56 -56
  252. data/schemas/tlc/1.0.9/sxl_index.json +226 -244
  253. data/schemas/tlc/1.1.0/alarms/A0007.json +25 -19
  254. data/schemas/tlc/1.1.0/alarms/A0008.json +21 -15
  255. data/schemas/tlc/1.1.0/alarms/A0201.json +26 -20
  256. data/schemas/tlc/1.1.0/alarms/A0202.json +26 -20
  257. data/schemas/tlc/1.1.0/alarms/A0301.json +69 -63
  258. data/schemas/tlc/1.1.0/alarms/A0302.json +87 -81
  259. data/schemas/tlc/1.1.0/alarms/A0303.json +69 -63
  260. data/schemas/tlc/1.1.0/alarms/A0304.json +87 -81
  261. data/schemas/tlc/1.1.0/commands/M0001.json +66 -60
  262. data/schemas/tlc/1.1.0/commands/M0002.json +48 -42
  263. data/schemas/tlc/1.1.0/commands/M0003.json +48 -42
  264. data/schemas/tlc/1.1.0/commands/M0004.json +35 -29
  265. data/schemas/tlc/1.1.0/commands/M0005.json +48 -42
  266. data/schemas/tlc/1.1.0/commands/M0006.json +48 -42
  267. data/schemas/tlc/1.1.0/commands/M0007.json +35 -29
  268. data/schemas/tlc/1.1.0/commands/M0008.json +48 -42
  269. data/schemas/tlc/1.1.0/commands/M0010.json +35 -29
  270. data/schemas/tlc/1.1.0/commands/M0011.json +35 -29
  271. data/schemas/tlc/1.1.0/commands/M0012.json +35 -29
  272. data/schemas/tlc/1.1.0/commands/M0013.json +35 -29
  273. data/schemas/tlc/1.1.0/commands/M0014.json +48 -42
  274. data/schemas/tlc/1.1.0/commands/M0015.json +48 -42
  275. data/schemas/tlc/1.1.0/commands/M0016.json +35 -29
  276. data/schemas/tlc/1.1.0/commands/M0017.json +35 -29
  277. data/schemas/tlc/1.1.0/commands/M0018.json +48 -42
  278. data/schemas/tlc/1.1.0/commands/M0019.json +61 -55
  279. data/schemas/tlc/1.1.0/commands/M0020.json +61 -55
  280. data/schemas/tlc/1.1.0/commands/M0021.json +35 -29
  281. data/schemas/tlc/1.1.0/commands/M0022.json +194 -188
  282. data/schemas/tlc/1.1.0/commands/M0023.json +35 -29
  283. data/schemas/tlc/1.1.0/commands/M0103.json +51 -45
  284. data/schemas/tlc/1.1.0/commands/M0104.json +100 -94
  285. data/schemas/tlc/1.1.0/commands/command_requests.json +1525 -1
  286. data/schemas/tlc/1.1.0/defs/guards.json +19 -0
  287. data/schemas/tlc/1.1.0/statuses/S0033.json +2 -2
  288. data/schemas/tlc/1.1.0/sxl.yaml +75 -74
  289. data/schemas/tlc/1.1.0/sxl_index.json +391 -398
  290. data/schemas/tlc/1.2.0/alarms/A0007.json +25 -19
  291. data/schemas/tlc/1.2.0/alarms/A0008.json +21 -15
  292. data/schemas/tlc/1.2.0/alarms/A0201.json +26 -20
  293. data/schemas/tlc/1.2.0/alarms/A0202.json +26 -20
  294. data/schemas/tlc/1.2.0/alarms/A0301.json +69 -63
  295. data/schemas/tlc/1.2.0/alarms/A0302.json +87 -81
  296. data/schemas/tlc/1.2.0/alarms/A0303.json +69 -63
  297. data/schemas/tlc/1.2.0/alarms/A0304.json +87 -81
  298. data/schemas/tlc/1.2.0/commands/M0001.json +66 -60
  299. data/schemas/tlc/1.2.0/commands/M0002.json +48 -42
  300. data/schemas/tlc/1.2.0/commands/M0003.json +48 -42
  301. data/schemas/tlc/1.2.0/commands/M0004.json +35 -29
  302. data/schemas/tlc/1.2.0/commands/M0005.json +48 -42
  303. data/schemas/tlc/1.2.0/commands/M0006.json +48 -42
  304. data/schemas/tlc/1.2.0/commands/M0007.json +35 -29
  305. data/schemas/tlc/1.2.0/commands/M0008.json +48 -42
  306. data/schemas/tlc/1.2.0/commands/M0010.json +35 -29
  307. data/schemas/tlc/1.2.0/commands/M0011.json +35 -29
  308. data/schemas/tlc/1.2.0/commands/M0012.json +35 -29
  309. data/schemas/tlc/1.2.0/commands/M0013.json +35 -29
  310. data/schemas/tlc/1.2.0/commands/M0014.json +48 -42
  311. data/schemas/tlc/1.2.0/commands/M0015.json +48 -42
  312. data/schemas/tlc/1.2.0/commands/M0016.json +35 -29
  313. data/schemas/tlc/1.2.0/commands/M0017.json +35 -29
  314. data/schemas/tlc/1.2.0/commands/M0018.json +48 -42
  315. data/schemas/tlc/1.2.0/commands/M0019.json +61 -55
  316. data/schemas/tlc/1.2.0/commands/M0020.json +61 -55
  317. data/schemas/tlc/1.2.0/commands/M0021.json +35 -29
  318. data/schemas/tlc/1.2.0/commands/M0022.json +194 -188
  319. data/schemas/tlc/1.2.0/commands/M0023.json +35 -29
  320. data/schemas/tlc/1.2.0/commands/M0103.json +51 -45
  321. data/schemas/tlc/1.2.0/commands/M0104.json +100 -94
  322. data/schemas/tlc/1.2.0/commands/command_requests.json +1525 -1
  323. data/schemas/tlc/1.2.0/defs/guards.json +19 -0
  324. data/schemas/tlc/1.2.0/statuses/S0033.json +2 -2
  325. data/schemas/tlc/1.2.0/sxl.yaml +77 -76
  326. data/schemas/tlc/1.2.0/sxl_index.json +401 -397
  327. data/schemas/tlc/1.2.1/alarms/A0007.json +25 -19
  328. data/schemas/tlc/1.2.1/alarms/A0008.json +21 -15
  329. data/schemas/tlc/1.2.1/alarms/A0201.json +26 -20
  330. data/schemas/tlc/1.2.1/alarms/A0202.json +26 -20
  331. data/schemas/tlc/1.2.1/alarms/A0301.json +69 -63
  332. data/schemas/tlc/1.2.1/alarms/A0302.json +87 -81
  333. data/schemas/tlc/1.2.1/alarms/A0303.json +69 -63
  334. data/schemas/tlc/1.2.1/alarms/A0304.json +87 -81
  335. data/schemas/tlc/1.2.1/commands/M0001.json +66 -60
  336. data/schemas/tlc/1.2.1/commands/M0002.json +48 -42
  337. data/schemas/tlc/1.2.1/commands/M0003.json +48 -42
  338. data/schemas/tlc/1.2.1/commands/M0004.json +35 -29
  339. data/schemas/tlc/1.2.1/commands/M0005.json +48 -42
  340. data/schemas/tlc/1.2.1/commands/M0006.json +48 -42
  341. data/schemas/tlc/1.2.1/commands/M0007.json +35 -29
  342. data/schemas/tlc/1.2.1/commands/M0008.json +48 -42
  343. data/schemas/tlc/1.2.1/commands/M0010.json +35 -29
  344. data/schemas/tlc/1.2.1/commands/M0011.json +35 -29
  345. data/schemas/tlc/1.2.1/commands/M0012.json +35 -29
  346. data/schemas/tlc/1.2.1/commands/M0013.json +35 -29
  347. data/schemas/tlc/1.2.1/commands/M0014.json +48 -42
  348. data/schemas/tlc/1.2.1/commands/M0015.json +48 -42
  349. data/schemas/tlc/1.2.1/commands/M0016.json +35 -29
  350. data/schemas/tlc/1.2.1/commands/M0017.json +35 -29
  351. data/schemas/tlc/1.2.1/commands/M0018.json +48 -42
  352. data/schemas/tlc/1.2.1/commands/M0019.json +61 -55
  353. data/schemas/tlc/1.2.1/commands/M0020.json +61 -55
  354. data/schemas/tlc/1.2.1/commands/M0021.json +35 -29
  355. data/schemas/tlc/1.2.1/commands/M0022.json +194 -188
  356. data/schemas/tlc/1.2.1/commands/M0023.json +35 -29
  357. data/schemas/tlc/1.2.1/commands/M0103.json +51 -45
  358. data/schemas/tlc/1.2.1/commands/M0104.json +100 -94
  359. data/schemas/tlc/1.2.1/commands/command_requests.json +1525 -1
  360. data/schemas/tlc/1.2.1/defs/guards.json +19 -0
  361. data/schemas/tlc/1.2.1/statuses/S0033.json +2 -2
  362. data/schemas/tlc/1.2.1/sxl.yaml +77 -76
  363. data/schemas/tlc/1.2.1/sxl_index.json +401 -397
  364. data/schemas/tlc/1.3.0/alarms/A0007.json +25 -19
  365. data/schemas/tlc/1.3.0/alarms/A0008.json +21 -15
  366. data/schemas/tlc/1.3.0/alarms/A0201.json +26 -20
  367. data/schemas/tlc/1.3.0/alarms/A0202.json +26 -20
  368. data/schemas/tlc/1.3.0/alarms/A0301.json +69 -63
  369. data/schemas/tlc/1.3.0/alarms/A0302.json +87 -81
  370. data/schemas/tlc/1.3.0/alarms/A0303.json +70 -64
  371. data/schemas/tlc/1.3.0/alarms/A0304.json +88 -82
  372. data/schemas/tlc/1.3.0/commands/M0001.json +66 -60
  373. data/schemas/tlc/1.3.0/commands/M0002.json +48 -42
  374. data/schemas/tlc/1.3.0/commands/M0003.json +48 -42
  375. data/schemas/tlc/1.3.0/commands/M0004.json +35 -29
  376. data/schemas/tlc/1.3.0/commands/M0005.json +48 -42
  377. data/schemas/tlc/1.3.0/commands/M0006.json +48 -42
  378. data/schemas/tlc/1.3.0/commands/M0007.json +35 -29
  379. data/schemas/tlc/1.3.0/commands/M0008.json +61 -55
  380. data/schemas/tlc/1.3.0/commands/M0010.json +35 -29
  381. data/schemas/tlc/1.3.0/commands/M0011.json +35 -29
  382. data/schemas/tlc/1.3.0/commands/M0012.json +35 -29
  383. data/schemas/tlc/1.3.0/commands/M0013.json +36 -30
  384. data/schemas/tlc/1.3.0/commands/M0014.json +48 -42
  385. data/schemas/tlc/1.3.0/commands/M0015.json +48 -42
  386. data/schemas/tlc/1.3.0/commands/M0016.json +35 -29
  387. data/schemas/tlc/1.3.0/commands/M0017.json +35 -29
  388. data/schemas/tlc/1.3.0/commands/M0018.json +48 -42
  389. data/schemas/tlc/1.3.0/commands/M0019.json +61 -55
  390. data/schemas/tlc/1.3.0/commands/M0020.json +61 -55
  391. data/schemas/tlc/1.3.0/commands/M0021.json +35 -29
  392. data/schemas/tlc/1.3.0/commands/M0022.json +195 -189
  393. data/schemas/tlc/1.3.0/commands/M0023.json +35 -29
  394. data/schemas/tlc/1.3.0/commands/M0024.json +21 -15
  395. data/schemas/tlc/1.3.0/commands/M0103.json +51 -45
  396. data/schemas/tlc/1.3.0/commands/M0104.json +100 -94
  397. data/schemas/tlc/1.3.0/commands/command_requests.json +1559 -1
  398. data/schemas/tlc/1.3.0/defs/guards.json +19 -0
  399. data/schemas/tlc/1.3.0/statuses/S0001.json +4 -4
  400. data/schemas/tlc/1.3.0/statuses/S0005.json +3 -3
  401. data/schemas/tlc/1.3.0/statuses/S0006.json +2 -2
  402. data/schemas/tlc/1.3.0/statuses/S0007.json +1 -1
  403. data/schemas/tlc/1.3.0/statuses/S0008.json +1 -1
  404. data/schemas/tlc/1.3.0/statuses/S0009.json +1 -1
  405. data/schemas/tlc/1.3.0/statuses/S0010.json +1 -1
  406. data/schemas/tlc/1.3.0/statuses/S0011.json +1 -1
  407. data/schemas/tlc/1.3.0/statuses/S0012.json +1 -1
  408. data/schemas/tlc/1.3.0/statuses/S0013.json +1 -1
  409. data/schemas/tlc/1.3.0/statuses/S0014.json +1 -1
  410. data/schemas/tlc/1.3.0/statuses/S0015.json +1 -1
  411. data/schemas/tlc/1.3.0/statuses/S0016.json +1 -1
  412. data/schemas/tlc/1.3.0/statuses/S0017.json +1 -1
  413. data/schemas/tlc/1.3.0/statuses/S0019.json +1 -1
  414. data/schemas/tlc/1.3.0/statuses/S0020.json +1 -1
  415. data/schemas/tlc/1.3.0/statuses/S0025.json +2 -2
  416. data/schemas/tlc/1.3.0/statuses/S0027.json +1 -1
  417. data/schemas/tlc/1.3.0/statuses/S0032.json +2 -2
  418. data/schemas/tlc/1.3.0/statuses/S0033.json +5 -5
  419. data/schemas/tlc/1.3.0/statuses/S0034.json +1 -1
  420. data/schemas/tlc/1.3.0/statuses/S0035.json +1 -1
  421. data/schemas/tlc/1.3.0/statuses/S0091.json +1 -1
  422. data/schemas/tlc/1.3.0/statuses/S0092.json +1 -1
  423. data/schemas/tlc/1.3.0/statuses/S0096.json +6 -6
  424. data/schemas/tlc/1.3.0/statuses/S0201.json +1 -1
  425. data/schemas/tlc/1.3.0/statuses/S0202.json +1 -1
  426. data/schemas/tlc/1.3.0/statuses/S0203.json +1 -1
  427. data/schemas/tlc/1.3.0/statuses/S0204.json +9 -9
  428. data/schemas/tlc/1.3.0/statuses/S0205.json +1 -1
  429. data/schemas/tlc/1.3.0/statuses/S0206.json +1 -1
  430. data/schemas/tlc/1.3.0/statuses/S0207.json +1 -1
  431. data/schemas/tlc/1.3.0/statuses/S0208.json +9 -9
  432. data/schemas/tlc/1.3.0/sxl_index.json +408 -402
  433. metadata +11 -1
@@ -8,42 +8,30 @@
8
8
  "propertyNames": { "not": { "const": "core" } },
9
9
  "additionalProperties": { "type": "string" }
10
10
  },
11
+ "core_version": { "type": "string" },
12
+ "rsmp_versions": {
13
+ "oneOf": [
14
+ { "type": "string" },
15
+ { "type": "array", "items": { "type": "string" } }
16
+ ]
17
+ },
11
18
  "type": { "type": "string" },
12
- "components": { "type": "object" },
19
+ "components": { "$ref": "config_common.json#/$defs/components" },
13
20
  "supervisors": {
14
21
  "type": "array",
15
- "items": {
16
- "type": "object",
17
- "properties": {
18
- "ip": { "type": "string" },
19
- "port": { "type": ["integer", "string"] }
20
- },
21
- "required": ["ip", "port"],
22
- "additionalProperties": true
23
- }
24
- },
25
- "intervals": {
26
- "type": "object",
27
- "properties": {
28
- "timer": { "type": "number" },
29
- "watchdog": { "type": "number" },
30
- "reconnect": { "type": "number" },
31
- "after_connect": { "type": "number" }
32
- },
33
- "additionalProperties": true
34
- },
35
- "timeouts": {
36
- "type": "object",
37
- "properties": {
38
- "connect": { "type": "number" },
39
- "watchdog": { "type": "number" },
40
- "acknowledgement": { "type": "number" }
41
- },
42
- "additionalProperties": true
22
+ "items": { "$ref": "config_common.json#/$defs/endpoint" }
43
23
  },
24
+ "intervals": { "$ref": "config_common.json#/$defs/intervals" },
25
+ "timeouts": { "$ref": "config_common.json#/$defs/timeouts" },
44
26
  "send_after_connect": { "type": "boolean" },
27
+ "receive_alarms": { "type": "boolean" },
28
+ "message_buffer": { "$ref": "config_common.json#/$defs/message_buffer" },
45
29
  "skip_validation": { "type": "array", "items": { "type": "string" } },
46
- "security_codes": { "type": "object" }
30
+ "security_codes": { "$ref": "config_common.json#/$defs/security_codes" },
31
+ "startup_sequence": { "type": "string" },
32
+ "signal_plans": { "$ref": "config_common.json#/$defs/signal_plans" },
33
+ "inputs": { "$ref": "config_common.json#/$defs/inputs" },
34
+ "live_output": { "type": ["string", "null"] }
47
35
  },
48
- "additionalProperties": true
36
+ "additionalProperties": false
49
37
  }
@@ -12,8 +12,7 @@
12
12
  "inputs": { "type": "object" },
13
13
  "live_output": { "type": ["string", "null"] },
14
14
  "type": { "type": "string" }
15
- },
16
- "additionalProperties": true
15
+ }
17
16
  }
18
17
  ]
19
18
  }
@@ -5,28 +5,15 @@ module RSMP
5
5
  def defaults
6
6
  {
7
7
  'site_id' => 'RN+SI0001',
8
- 'supervisors' => [
9
- { 'ip' => '127.0.0.1', 'port' => 12_111 }
10
- ],
11
- 'sxls' => {
12
- 'tlc' => RSMP::Schema.latest_version(:tlc)
13
- },
14
- 'intervals' => {
15
- 'timer' => 0.1,
16
- 'watchdog' => 1,
17
- 'reconnect' => 0.1
18
- },
19
- 'timeouts' => {
20
- 'watchdog' => 2,
21
- 'acknowledgement' => 2
22
- },
8
+ 'connection_role' => 'client',
9
+ 'ip' => '0.0.0.0',
10
+ 'supervisors' => default_supervisors,
11
+ 'sxls' => default_sxls,
12
+ 'intervals' => default_intervals,
13
+ 'timeouts' => default_timeouts,
23
14
  'send_after_connect' => true,
24
15
  'message_buffer' => default_message_buffer,
25
- 'components' => {
26
- 'main' => {
27
- 'C1' => {}
28
- }
29
- }
16
+ 'components' => default_components
30
17
  }
31
18
  end
32
19
 
@@ -38,16 +25,37 @@ module RSMP
38
25
 
39
26
  def default_message_buffer
40
27
  {
41
- 'enabled' => true,
42
28
  'max_messages' => 10_000,
43
- 'statuses' => []
29
+ 'statuses' => true
44
30
  }
45
31
  end
46
32
 
33
+ def default_supervisors
34
+ [{ 'ip' => '127.0.0.1', 'port' => 12_111 }]
35
+ end
36
+
37
+ def default_sxls
38
+ { 'tlc' => RSMP::Schema.latest_version(:tlc) }
39
+ end
40
+
41
+ def default_intervals
42
+ { 'timer' => 0.1, 'watchdog' => 1, 'reconnect' => 0.1 }
43
+ end
44
+
45
+ def default_timeouts
46
+ { 'watchdog' => 2, 'acknowledgement' => 2 }
47
+ end
48
+
49
+ def default_components
50
+ { 'main' => { 'C1' => {} } }
51
+ end
52
+
47
53
  def apply_defaults(options)
48
54
  defaults = defaults()
49
55
  defaults['components']['main'] = options['components']['main'] if options.dig('components', 'main')
50
- defaults.deep_merge(options)
56
+ data = defaults.deep_merge(options)
57
+ data['port'] ||= data.dig('supervisors', 0, 'port')
58
+ data
51
59
  end
52
60
  end
53
61
  end
@@ -5,6 +5,7 @@ module RSMP
5
5
  def defaults
6
6
  {
7
7
  'port' => 12_111,
8
+ 'connection_role' => 'server',
8
9
  'ips' => 'all',
9
10
  'default' => {
10
11
  'sxls' => {
@@ -68,8 +68,10 @@ module RSMP
68
68
  def process_packet(json)
69
69
  attributes = Message.parse_attributes json
70
70
  message = Message.build attributes, json
71
- message.validate(schemas) if should_validate_ingoing_message?(message)
71
+ validate = should_validate_ingoing_message?(message)
72
+ message.validate(schemas) if validate
72
73
  verify_sequence message
74
+ message.decode_for(schemas) if validate
73
75
  with_deferred_distribution do
74
76
  distribute message
75
77
  process_message message
@@ -12,21 +12,12 @@ module RSMP
12
12
  end
13
13
 
14
14
  def send_message(message, reason = nil, validate: true, force: false, buffer: true)
15
- unless force || connected?
16
- error = NotReady.new
17
- raise error unless buffer
18
-
19
- return buffer_message(message, error)
15
+ with_send_ready(message, force: force, buffer: buffer) do
16
+ write_message(message, validate: validate)
17
+ expect_acknowledgement message
18
+ distribute message
19
+ log_send message, reason
20
20
  end
21
- raise IOError unless @protocol
22
-
23
- message.direction = :out
24
- message.generate_json
25
- message.validate schemas unless validate == false
26
- @protocol.write_lines message.json
27
- expect_acknowledgement message
28
- distribute message
29
- log_send message, reason
30
21
  rescue NotReady, IOError => e
31
22
  raise e unless buffer
32
23
 
@@ -35,6 +26,25 @@ module RSMP
35
26
  handle_send_schema_error(message, e)
36
27
  end
37
28
 
29
+ def with_send_ready(message, force:, buffer:)
30
+ return yield if force || connected?
31
+
32
+ error = NotReady.new
33
+ raise error unless buffer
34
+
35
+ buffer_message(message, error)
36
+ end
37
+
38
+ def write_message(message, validate:)
39
+ raise IOError unless @protocol
40
+
41
+ message.direction = :out
42
+ message.encode_for(schemas) unless validate == false
43
+ message.generate_json
44
+ message.validate schemas unless validate == false
45
+ @protocol.write_lines message.json
46
+ end
47
+
38
48
  def buffer_message(message, error = nil)
39
49
  str = "Cannot send #{message.type} because the connection is closed."
40
50
  log str, message: message, level: :error
@@ -67,6 +77,8 @@ module RSMP
67
77
  end
68
78
 
69
79
  def apply_nts_message_attributes(message)
80
+ return if core_3_3?
81
+
70
82
  message.attributes['ntsOId'] = main && main.ntsoid ? main.ntsoid : ''
71
83
  message.attributes['xNId'] = main && main.xnid ? main.xnid : ''
72
84
  end
@@ -234,6 +234,23 @@ module RSMP
234
234
  sxl_interface resolved.first
235
235
  end
236
236
 
237
+ def command_items(message)
238
+ key = message.is_a?(CommandResponse) ? 'rvs' : 'arg'
239
+ message.attributes[key] || []
240
+ end
241
+
242
+ def command_codes(message)
243
+ command_items(message).map { |item| item['cCI'] }.compact.uniq
244
+ end
245
+
246
+ def multiple_command_codes?(message)
247
+ command_codes(message).size > 1
248
+ end
249
+
250
+ def reject_multiple_command_codes(message)
251
+ dont_acknowledge message, 'Rejected', 'more than one command code in a single command message'
252
+ end
253
+
237
254
  # Use Gem class to check version requirement
238
255
  # Requirement must be a string like '1.1', '>=1.0.3' or '<2.1.4',
239
256
  # or list of strings, like ['<=1.4','<1.5']
@@ -0,0 +1,79 @@
1
+ module RSMP
2
+ # Connection management for supervisor-side site proxies.
3
+ module SiteProxyConnection
4
+ # handle communication
5
+ # when we're created, the socket is already open
6
+ def run
7
+ if @protocol
8
+ run_accepted_connection
9
+ else
10
+ run_outbound_connection
11
+ end
12
+ end
13
+
14
+ def run_accepted_connection
15
+ self.state = :connected
16
+ start_reader
17
+ wait_for_reader # run until disconnected
18
+ rescue RSMP::ConnectionError => e
19
+ log e, level: :error
20
+ rescue StandardError => e
21
+ distribute_error e, level: :internal
22
+ ensure
23
+ close
24
+ end
25
+
26
+ def run_outbound_connection
27
+ loop do
28
+ setup_site_settings
29
+ connect
30
+ start_reader
31
+ wait_for_reader
32
+ break unless reconnect_delay?
33
+ rescue Restart
34
+ @logger.mute @ip, @port
35
+ raise
36
+ rescue RSMP::ConnectionError => e
37
+ log e, level: :error
38
+ break unless reconnect_delay?
39
+ rescue StandardError => e
40
+ distribute_error e, level: :internal
41
+ break unless reconnect_delay?
42
+ ensure
43
+ close
44
+ stop_subtasks
45
+ end
46
+ end
47
+
48
+ def connect
49
+ log "Connecting to site #{@site_id} at #{@ip}:#{@port}", level: :info
50
+ self.state = :connecting
51
+ open_socket
52
+ self.state = :connected
53
+ @logger.unmute @ip, @port
54
+ log "Connected to site #{@site_id} at #{@ip}:#{@port}", level: :info
55
+ rescue SystemCallError => e
56
+ raise ConnectionError, "Could not connect to site #{@site_id} at #{@ip}:#{@port}: Errno #{e.errno} #{e}"
57
+ rescue StandardError => e
58
+ raise ConnectionError, "Error while connecting to site #{@site_id} at #{@ip}:#{@port}: #{e}"
59
+ end
60
+
61
+ def open_socket
62
+ endpoint = IO::Endpoint.tcp(@ip, @port)
63
+ timeout = @site_settings.dig('timeouts', 'connect') || 1.1
64
+ task.with_timeout(timeout) { @socket = endpoint.connect }
65
+ @stream = IO::Stream::Buffered.new(@socket)
66
+ @protocol = RSMP::Protocol.new(@stream)
67
+ end
68
+
69
+ def reconnect_delay?
70
+ return false if @site_settings['intervals']['reconnect'] == :no
71
+
72
+ interval = @site_settings['intervals']['reconnect'] || 0.1
73
+ log "Will try to reconnect again every #{interval} seconds...", level: :info
74
+ @logger.mute @ip, @port
75
+ @task.sleep interval
76
+ true
77
+ end
78
+ end
79
+ end
@@ -24,17 +24,40 @@ module RSMP
24
24
  validate_ready 'send command'
25
25
  component ||= main.c_id
26
26
  m_id = RSMP::Message.make_m_id
27
+ collector_list = command_collector_list(command_list)
27
28
  message = RSMP::CommandRequest.new({
28
29
  'cId' => component,
29
30
  'arg' => command_list,
30
31
  'mId' => m_id
31
32
  })
32
33
  apply_nts_message_attributes message
33
- collector = CommandResponseCollector.new(self, command_list, timeout: within, initiator: message)
34
+ collector = CommandResponseCollector.new(self, collector_list, timeout: within, initiator: message)
34
35
  send_message_and_collect(message, collector, validate: validate)[:collector]
35
36
  end
36
37
 
38
+ def command_collector_list(command_list)
39
+ list = JSON.parse(JSON.generate(command_list))
40
+ resolved = RSMP::Schema.resolve_sxl({ 'type' => 'CommandRequest', 'arg' => list }, schemas: schemas)
41
+ return list unless resolved
42
+
43
+ type, version = resolved
44
+ list.each do |item|
45
+ next unless item.key?('v')
46
+
47
+ descriptor = RSMP::Schema.sxl_argument_descriptor(type, version, :commands, item['cCI'], item['n'])
48
+ next unless descriptor
49
+
50
+ encoded = RSMP::Message.encode_sxl_value(item['v'], descriptor)
51
+ item['v'] = RSMP::Message.decode_sxl_value(encoded, descriptor)
52
+ end
53
+ list
54
+ rescue RSMP::Schema::Error
55
+ list
56
+ end
57
+
37
58
  def process_command_response(message)
59
+ return reject_multiple_command_codes(message) if core_3_3? && multiple_command_codes?(message)
60
+
38
61
  log "Received #{message.type}", message: message, level: :log
39
62
  acknowledge message
40
63
  end
@@ -6,6 +6,7 @@ module RSMP
6
6
  include Modules::AggregatedStatus
7
7
  include Modules::Alarms
8
8
  include Modules::Commands
9
+ include SiteProxyConnection
9
10
  include SiteSxlSelection
10
11
 
11
12
  attr_reader :supervisor, :site_id
@@ -16,27 +17,15 @@ module RSMP
16
17
  @supervisor = options[:supervisor]
17
18
  @settings = @supervisor.supervisor_settings.clone
18
19
  @site_id = options[:site_id]
20
+ @configured_site_settings = options[:site_settings]
19
21
  @status_subscriptions = {}
20
22
  end
21
23
 
22
- # handle communication
23
- # when we're created, the socket is already open
24
- def run
25
- self.state = :connected
26
- start_reader
27
- wait_for_reader # run until disconnected
28
- rescue RSMP::ConnectionError => e
29
- log e, level: :error
30
- rescue StandardError => e
31
- distribute_error e, level: :internal
32
- ensure
33
- close
34
- end
35
-
36
24
  def revive(options)
37
25
  super
38
26
  @supervisor = options[:supervisor]
39
27
  @settings = @supervisor.supervisor_settings.clone
28
+ @configured_site_settings = options[:site_settings]
40
29
  end
41
30
 
42
31
  def node
@@ -170,6 +159,7 @@ module RSMP
170
159
  return extraneous_version message if @version_determined
171
160
 
172
161
  check_site_ids message
162
+ check_core_version message
173
163
  check_sxl_version message
174
164
  version_accepted message
175
165
  end
@@ -177,6 +167,7 @@ module RSMP
177
167
  def check_site_ids(message)
178
168
  # RSMP support multiple site ids. we don't support this yet. instead we use the first id only
179
169
  site_id = message.attribute('siteId').map { |item| item['sId'] }.first
170
+ @site_id ||= site_id
180
171
  @supervisor.check_site_id site_id
181
172
  site_ids_changed
182
173
  end
@@ -202,7 +193,7 @@ module RSMP
202
193
  end
203
194
 
204
195
  def setup_site_settings
205
- @site_settings = find_site_settings @site_id
196
+ @site_settings = @configured_site_settings || find_site_settings(@site_id)
206
197
  if @site_settings
207
198
  @sxls = configured_sxls
208
199
  @accepted_sxls = @sxls.dup
@@ -20,11 +20,63 @@ module RSMP
20
20
  end
21
21
  end
22
22
 
23
+ def command_catalogue_item(command_code)
24
+ accepted_sxls.each do |sxl|
25
+ item = command_catalogue_match(sxl, command_code)
26
+ return item if item
27
+ end
28
+ nil
29
+ end
30
+
31
+ def command_catalogue_match(sxl, command_code)
32
+ version = RSMP::Schema.sanitize_version(sxl['version'].to_s)
33
+ catalogue = RSMP::Schema.sxl_catalogue(sxl['name'], version, :commands)
34
+ prefix = RSMP::Schema.sxl_prefix(sxl['name'], version, lenient: true)
35
+ lookup_catalogue_command(catalogue, command_code, prefix)
36
+ end
37
+
38
+ def lookup_catalogue_command(catalogue, command_code, prefix)
39
+ unprefixed = prefix && command_code.start_with?(prefix) ? command_code[prefix.length..] : command_code
40
+ catalogue[command_code] || catalogue[command_code.to_sym] ||
41
+ catalogue[unprefixed] || catalogue[unprefixed.to_sym]
42
+ end
43
+
44
+ def required_command_argument_names(command_code)
45
+ item = command_catalogue_item command_code
46
+ return [] unless item
47
+
48
+ RSMP::Schema.argument_names(item['required'])
49
+ end
50
+
51
+ def check_required_command_arguments(message)
52
+ return unless core_3_3?
53
+
54
+ command_codes(message).each do |command_code|
55
+ provided = message.attributes['arg'].select { |item| item['cCI'] == command_code }.map { |item| item['n'] }
56
+ missing = required_command_argument_names(command_code) - provided
57
+ next if missing.empty?
58
+
59
+ raise MissingAttribute, "Missing required command argument(s) #{missing.join(', ')} for #{command_code}"
60
+ end
61
+ end
62
+
63
+ def mark_command_unknown(rvs, command_code)
64
+ rvs.each do |item|
65
+ next unless item['cCI'] == command_code
66
+
67
+ item['age'] = 'unknown'
68
+ item['v'] = nil
69
+ end
70
+ end
71
+
23
72
  def execute_commands(message, component_id, rvs)
24
73
  component = @site.find_component component_id
25
74
  commands = simplify_command_requests message.attributes['arg']
26
75
  commands.each_pair do |command_code, arg|
27
76
  component.handle_command command_code, arg
77
+ rescue UnknownCommand => e
78
+ log e.to_s, message: message, level: :warning
79
+ mark_command_unknown rvs, command_code
28
80
  end
29
81
  log "Received #{message.type}", message: message, level: :log
30
82
  rescue UnknownComponent
@@ -34,6 +86,9 @@ module RSMP
34
86
  end
35
87
 
36
88
  def process_command_request(message)
89
+ return reject_multiple_command_codes(message) if core_3_3? && multiple_command_codes?(message)
90
+
91
+ check_required_command_arguments message
37
92
  component_id = message.attributes['cId']
38
93
  rvs = build_command_rvs(message.attributes['arg'])
39
94
  execute_commands(message, component_id, rvs)
@@ -7,10 +7,6 @@ module RSMP
7
7
  @site_settings['message_buffer'] || {}
8
8
  end
9
9
 
10
- def message_buffer_enabled?
11
- message_buffer_settings['enabled'] != false
12
- end
13
-
14
10
  def message_buffer_max_messages
15
11
  message_buffer_settings['max_messages'] || 10_000
16
12
  end
@@ -79,7 +75,6 @@ module RSMP
79
75
  end
80
76
 
81
77
  def prepare_message_for_buffer(message, core_version: @core_version, for_send: false)
82
- return unless message_buffer_enabled?
83
78
  return unless site_originated_buffer_candidate? message
84
79
  return false if message.is_a?(RSMP::StatusUpdate) && status_buffer_selectors == false
85
80
  return false if message.is_a?(RSMP::Alarm) && !receive_alarms?
@@ -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