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
@@ -2,8 +2,9 @@ module RSMP
2
2
  # RSMP site implementation that manages proxies and components.
3
3
  class Site < Node
4
4
  include Components
5
+ include SiteConnections
5
6
 
6
- attr_reader :core_version, :site_settings, :logger, :proxies
7
+ attr_reader :core_version, :site_settings, :logger, :proxies, :ready_condition
7
8
 
8
9
  def self.options_class
9
10
  RSMP::Site::Options
@@ -16,6 +17,7 @@ module RSMP
16
17
  @proxies = []
17
18
  @sleep_condition = Async::Notification.new
18
19
  @proxies_condition = Async::Notification.new
20
+ @ready_condition = Async::Notification.new
19
21
  build_proxies
20
22
  end
21
23
 
@@ -35,6 +37,14 @@ module RSMP
35
37
  @site_settings['site_id']
36
38
  end
37
39
 
40
+ def client_role?
41
+ @site_settings['connection_role'] != 'server'
42
+ end
43
+
44
+ def server_role?
45
+ @site_settings['connection_role'] == 'server'
46
+ end
47
+
38
48
  def handle_site_settings(options = {})
39
49
  options_class = self.class.options_class
40
50
  settings = options[:site_settings] || {}
@@ -97,22 +107,11 @@ module RSMP
97
107
  def run
98
108
  log_site_starting
99
109
  start_status_timer
100
- @proxies.each(&:start)
101
- @proxies.each(&:wait)
102
- end
103
-
104
- def build_proxies
105
- @site_settings['supervisors'].each do |supervisor_settings|
106
- @proxies << SupervisorProxy.new({
107
- site: self,
108
- task: @task,
109
- settings: @site_settings,
110
- ip: supervisor_settings['ip'],
111
- port: supervisor_settings['port'],
112
- logger: @logger,
113
- archive: @archive,
114
- collect: @collect
115
- })
110
+ if server_role?
111
+ listen_for_supervisors
112
+ else
113
+ @proxies.each(&:start)
114
+ @proxies.each(&:wait)
116
115
  end
117
116
  end
118
117
 
@@ -177,36 +176,23 @@ module RSMP
177
176
 
178
177
  def stop_subtasks
179
178
  stop_status_timer
179
+ @accept_task&.stop
180
+ @accept_task = nil
181
+ @endpoint = nil
180
182
  super
181
183
  end
182
184
 
183
- def connect_to_supervisor(_task, supervisor_settings)
184
- proxy = build_proxy({
185
- site: self,
186
- task: @task,
187
- settings: @site_settings,
188
- ip: supervisor_settings['ip'],
189
- port: supervisor_settings['port'],
190
- logger: @logger,
191
- archive: @archive,
192
- collect: @collect
193
- })
194
- @proxies << proxy
195
- proxy.start
196
- @proxies_condition.signal
197
- end
198
-
199
185
  # stop
200
186
  def stop
201
187
  log "Stopping site #{@site_settings['site_id']}", level: :info
202
188
  super
203
189
  end
204
190
 
205
- def wait_for_supervisor(ip, timeout)
191
+ def wait_for_supervisor(ip, timeout:)
206
192
  supervisor = find_supervisor ip
207
193
  return supervisor if supervisor
208
194
 
209
- wait_for_condition(@proxy_condition, timeout: timeout) { find_supervisor ip }
195
+ wait_for_condition(@proxies_condition, timeout: timeout) { find_supervisor ip }
210
196
  rescue Async::TimeoutError
211
197
  raise RSMP::TimeoutError, "Supervisor '#{ip}' did not connect within #{timeout}s"
212
198
  end
@@ -21,8 +21,18 @@ module RSMP
21
21
  @supervisor_settings['site_id']
22
22
  end
23
23
 
24
+ def client_role?
25
+ @supervisor_settings['connection_role'] == 'client'
26
+ end
27
+
28
+ def server_role?
29
+ !client_role?
30
+ end
31
+
24
32
  # listen for connections
25
33
  def run
34
+ return connect_to_sites if client_role?
35
+
26
36
  log "Starting supervisor on port #{@supervisor_settings['port']}",
27
37
  level: :info,
28
38
  timestamp: @clock.now
@@ -47,6 +57,38 @@ module RSMP
47
57
  distribute_error e, level: :internal
48
58
  end
49
59
 
60
+ def connect_to_sites
61
+ log 'Starting supervisor in client connection role',
62
+ level: :info,
63
+ timestamp: @clock.now
64
+ build_outbound_proxies
65
+ @ready_condition.signal
66
+ @proxies.each(&:start)
67
+ @proxies.each(&:wait)
68
+ end
69
+
70
+ def build_outbound_proxies
71
+ site_entries = (@supervisor_settings['sites'] || {}).except('default')
72
+ site_entries.each_pair do |site_id, site_settings|
73
+ endpoints = site_settings['supervisors'] || []
74
+ merged_settings = site_id_to_site_setting site_id
75
+ endpoints.each do |endpoint|
76
+ @proxies << SiteProxy.new({
77
+ supervisor: self,
78
+ task: @task,
79
+ settings: @supervisor_settings,
80
+ site_id: site_id,
81
+ site_settings: merged_settings,
82
+ ip: endpoint['ip'],
83
+ port: endpoint['port'],
84
+ logger: @logger,
85
+ archive: @archive,
86
+ collect: @collect
87
+ })
88
+ end
89
+ end
90
+ end
91
+
50
92
  # stop
51
93
  def stop
52
94
  log "Stopping supervisor #{@supervisor_settings['site_id']}", level: :info
@@ -5,6 +5,9 @@
5
5
  "properties": {
6
6
  "site_id": { "type": "string" },
7
7
  "type": { "type": "string" },
8
+ "connection_role": { "enum": ["client", "server"] },
9
+ "ip": { "type": "string" },
10
+ "port": { "type": ["integer", "string"] },
8
11
  "supervisors": {
9
12
  "type": "array",
10
13
  "items": { "$ref": "config_common.json#/$defs/endpoint" }
@@ -4,6 +4,7 @@
4
4
  "properties": {
5
5
  "port": { "type": ["integer", "string"] },
6
6
  "ip": { "type": "string" },
7
+ "connection_role": { "enum": ["client", "server"] },
7
8
  "proxy_type": { "type": "string" },
8
9
  "ips": {
9
10
  "oneOf": [
@@ -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
 
@@ -43,10 +30,32 @@ module RSMP
43
30
  }
44
31
  end
45
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
+
46
53
  def apply_defaults(options)
47
54
  defaults = defaults()
48
55
  defaults['components']['main'] = options['components']['main'] if options.dig('components', 'main')
49
- defaults.deep_merge(options)
56
+ data = defaults.deep_merge(options)
57
+ data['port'] ||= data.dig('supervisors', 0, 'port')
58
+ data
50
59
  end
51
60
  end
52
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)