javi-forge 1.2.0 → 1.3.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 (228) hide show
  1. package/ci-local/ci-local.sh +20 -8
  2. package/package.json +1 -1
  3. package/ai-config/.skillignore +0 -15
  4. package/ai-config/AUTO_INVOKE.md +0 -300
  5. package/ai-config/agents/_TEMPLATE.md +0 -93
  6. package/ai-config/agents/business/api-designer.md +0 -1657
  7. package/ai-config/agents/business/business-analyst.md +0 -1331
  8. package/ai-config/agents/business/product-strategist.md +0 -206
  9. package/ai-config/agents/business/project-manager.md +0 -178
  10. package/ai-config/agents/business/requirements-analyst.md +0 -1277
  11. package/ai-config/agents/business/technical-writer.md +0 -1679
  12. package/ai-config/agents/creative/ux-designer.md +0 -205
  13. package/ai-config/agents/data-ai/ai-engineer.md +0 -487
  14. package/ai-config/agents/data-ai/analytics-engineer.md +0 -953
  15. package/ai-config/agents/data-ai/data-engineer.md +0 -173
  16. package/ai-config/agents/data-ai/data-scientist.md +0 -672
  17. package/ai-config/agents/data-ai/mlops-engineer.md +0 -814
  18. package/ai-config/agents/data-ai/prompt-engineer.md +0 -772
  19. package/ai-config/agents/development/angular-expert.md +0 -620
  20. package/ai-config/agents/development/backend-architect.md +0 -795
  21. package/ai-config/agents/development/database-specialist.md +0 -212
  22. package/ai-config/agents/development/frontend-specialist.md +0 -686
  23. package/ai-config/agents/development/fullstack-engineer.md +0 -668
  24. package/ai-config/agents/development/golang-pro.md +0 -338
  25. package/ai-config/agents/development/java-enterprise.md +0 -400
  26. package/ai-config/agents/development/javascript-pro.md +0 -422
  27. package/ai-config/agents/development/nextjs-pro.md +0 -474
  28. package/ai-config/agents/development/python-pro.md +0 -570
  29. package/ai-config/agents/development/react-pro.md +0 -487
  30. package/ai-config/agents/development/rust-pro.md +0 -246
  31. package/ai-config/agents/development/spring-boot-4-expert.md +0 -326
  32. package/ai-config/agents/development/typescript-pro.md +0 -336
  33. package/ai-config/agents/development/vue-specialist.md +0 -605
  34. package/ai-config/agents/infrastructure/cloud-architect.md +0 -472
  35. package/ai-config/agents/infrastructure/deployment-manager.md +0 -358
  36. package/ai-config/agents/infrastructure/devops-engineer.md +0 -455
  37. package/ai-config/agents/infrastructure/incident-responder.md +0 -519
  38. package/ai-config/agents/infrastructure/kubernetes-expert.md +0 -705
  39. package/ai-config/agents/infrastructure/monitoring-specialist.md +0 -674
  40. package/ai-config/agents/infrastructure/performance-engineer.md +0 -658
  41. package/ai-config/agents/orchestrator.md +0 -241
  42. package/ai-config/agents/quality/accessibility-auditor.md +0 -1204
  43. package/ai-config/agents/quality/code-reviewer-compact.md +0 -123
  44. package/ai-config/agents/quality/code-reviewer.md +0 -363
  45. package/ai-config/agents/quality/dependency-manager.md +0 -743
  46. package/ai-config/agents/quality/e2e-test-specialist.md +0 -1005
  47. package/ai-config/agents/quality/performance-tester.md +0 -1086
  48. package/ai-config/agents/quality/security-auditor.md +0 -133
  49. package/ai-config/agents/quality/test-engineer.md +0 -453
  50. package/ai-config/agents/specialists/api-designer.md +0 -87
  51. package/ai-config/agents/specialists/backend-architect.md +0 -73
  52. package/ai-config/agents/specialists/code-reviewer.md +0 -77
  53. package/ai-config/agents/specialists/db-optimizer.md +0 -75
  54. package/ai-config/agents/specialists/devops-engineer.md +0 -83
  55. package/ai-config/agents/specialists/documentation-writer.md +0 -78
  56. package/ai-config/agents/specialists/frontend-developer.md +0 -75
  57. package/ai-config/agents/specialists/performance-analyst.md +0 -82
  58. package/ai-config/agents/specialists/refactor-specialist.md +0 -74
  59. package/ai-config/agents/specialists/security-auditor.md +0 -74
  60. package/ai-config/agents/specialists/test-engineer.md +0 -81
  61. package/ai-config/agents/specialists/ux-consultant.md +0 -76
  62. package/ai-config/agents/specialized/agent-generator.md +0 -1190
  63. package/ai-config/agents/specialized/blockchain-developer.md +0 -149
  64. package/ai-config/agents/specialized/code-migrator.md +0 -892
  65. package/ai-config/agents/specialized/context-manager.md +0 -978
  66. package/ai-config/agents/specialized/documentation-writer.md +0 -1078
  67. package/ai-config/agents/specialized/ecommerce-expert.md +0 -1756
  68. package/ai-config/agents/specialized/embedded-engineer.md +0 -1714
  69. package/ai-config/agents/specialized/error-detective.md +0 -1034
  70. package/ai-config/agents/specialized/fintech-specialist.md +0 -1659
  71. package/ai-config/agents/specialized/freelance-project-planner-v2.md +0 -1988
  72. package/ai-config/agents/specialized/freelance-project-planner-v3.md +0 -2136
  73. package/ai-config/agents/specialized/freelance-project-planner-v4.md +0 -4503
  74. package/ai-config/agents/specialized/freelance-project-planner.md +0 -722
  75. package/ai-config/agents/specialized/game-developer.md +0 -1963
  76. package/ai-config/agents/specialized/healthcare-dev.md +0 -1620
  77. package/ai-config/agents/specialized/mobile-developer.md +0 -188
  78. package/ai-config/agents/specialized/parallel-plan-executor.md +0 -506
  79. package/ai-config/agents/specialized/plan-executor.md +0 -485
  80. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +0 -485
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +0 -3493
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +0 -778
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +0 -918
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +0 -1537
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +0 -2633
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +0 -5610
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +0 -335
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +0 -215
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +0 -260
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +0 -379
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +0 -355
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +0 -279
  93. package/ai-config/agents/specialized/template-writer.md +0 -347
  94. package/ai-config/agents/specialized/test-runner.md +0 -99
  95. package/ai-config/agents/specialized/vibekanban-smart-worker.md +0 -244
  96. package/ai-config/agents/specialized/wave-executor.md +0 -138
  97. package/ai-config/agents/specialized/workflow-optimizer.md +0 -1114
  98. package/ai-config/commands/git/changelog.md +0 -32
  99. package/ai-config/commands/git/ci-local.md +0 -70
  100. package/ai-config/commands/git/commit.md +0 -35
  101. package/ai-config/commands/git/fix-issue.md +0 -23
  102. package/ai-config/commands/git/pr-create.md +0 -42
  103. package/ai-config/commands/git/pr-review.md +0 -50
  104. package/ai-config/commands/git/worktree.md +0 -39
  105. package/ai-config/commands/refactoring/cleanup.md +0 -24
  106. package/ai-config/commands/refactoring/dead-code.md +0 -40
  107. package/ai-config/commands/refactoring/extract.md +0 -31
  108. package/ai-config/commands/testing/e2e.md +0 -30
  109. package/ai-config/commands/testing/tdd.md +0 -36
  110. package/ai-config/commands/testing/test-coverage.md +0 -30
  111. package/ai-config/commands/testing/test-fix.md +0 -24
  112. package/ai-config/commands/workflow/generate-agents-md.md +0 -85
  113. package/ai-config/commands/workflow/planning.md +0 -47
  114. package/ai-config/commands/workflows/compound.md +0 -89
  115. package/ai-config/commands/workflows/diagnose.md +0 -70
  116. package/ai-config/commands/workflows/discover.md +0 -86
  117. package/ai-config/commands/workflows/plan.md +0 -77
  118. package/ai-config/commands/workflows/review.md +0 -78
  119. package/ai-config/commands/workflows/work.md +0 -75
  120. package/ai-config/config.yaml +0 -18
  121. package/ai-config/hooks/_TEMPLATE.md +0 -96
  122. package/ai-config/hooks/block-dangerous-commands.md +0 -75
  123. package/ai-config/hooks/commit-guard.md +0 -90
  124. package/ai-config/hooks/context-loader.md +0 -73
  125. package/ai-config/hooks/improve-prompt.md +0 -91
  126. package/ai-config/hooks/learning-log.md +0 -72
  127. package/ai-config/hooks/model-router.md +0 -86
  128. package/ai-config/hooks/secret-scanner.md +0 -64
  129. package/ai-config/hooks/skill-validator.md +0 -102
  130. package/ai-config/hooks/task-artifact.md +0 -114
  131. package/ai-config/hooks/validate-workflow.md +0 -100
  132. package/ai-config/prompts/base.md +0 -71
  133. package/ai-config/prompts/modes/debug.md +0 -34
  134. package/ai-config/prompts/modes/deploy.md +0 -40
  135. package/ai-config/prompts/modes/research.md +0 -32
  136. package/ai-config/prompts/modes/review.md +0 -33
  137. package/ai-config/prompts/review-policy.md +0 -79
  138. package/ai-config/skills/_TEMPLATE.md +0 -157
  139. package/ai-config/skills/backend/api-gateway/SKILL.md +0 -254
  140. package/ai-config/skills/backend/bff-concepts/SKILL.md +0 -239
  141. package/ai-config/skills/backend/bff-spring/SKILL.md +0 -364
  142. package/ai-config/skills/backend/chi-router/SKILL.md +0 -396
  143. package/ai-config/skills/backend/error-handling/SKILL.md +0 -255
  144. package/ai-config/skills/backend/exceptions-spring/SKILL.md +0 -323
  145. package/ai-config/skills/backend/fastapi/SKILL.md +0 -302
  146. package/ai-config/skills/backend/gateway-spring/SKILL.md +0 -390
  147. package/ai-config/skills/backend/go-backend/SKILL.md +0 -457
  148. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +0 -274
  149. package/ai-config/skills/backend/graphql-concepts/SKILL.md +0 -352
  150. package/ai-config/skills/backend/graphql-spring/SKILL.md +0 -398
  151. package/ai-config/skills/backend/grpc-concepts/SKILL.md +0 -283
  152. package/ai-config/skills/backend/grpc-spring/SKILL.md +0 -445
  153. package/ai-config/skills/backend/jwt-auth/SKILL.md +0 -412
  154. package/ai-config/skills/backend/notifications-concepts/SKILL.md +0 -259
  155. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +0 -261
  156. package/ai-config/skills/backend/search-concepts/SKILL.md +0 -263
  157. package/ai-config/skills/backend/search-spring/SKILL.md +0 -375
  158. package/ai-config/skills/backend/spring-boot-4/SKILL.md +0 -172
  159. package/ai-config/skills/backend/websockets/SKILL.md +0 -532
  160. package/ai-config/skills/data-ai/ai-ml/SKILL.md +0 -423
  161. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +0 -195
  162. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +0 -340
  163. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +0 -440
  164. package/ai-config/skills/data-ai/langchain/SKILL.md +0 -238
  165. package/ai-config/skills/data-ai/mlflow/SKILL.md +0 -302
  166. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +0 -290
  167. package/ai-config/skills/data-ai/powerbi/SKILL.md +0 -352
  168. package/ai-config/skills/data-ai/pytorch/SKILL.md +0 -274
  169. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +0 -321
  170. package/ai-config/skills/data-ai/vector-db/SKILL.md +0 -301
  171. package/ai-config/skills/database/graph-databases/SKILL.md +0 -218
  172. package/ai-config/skills/database/graph-spring/SKILL.md +0 -361
  173. package/ai-config/skills/database/pgx-postgres/SKILL.md +0 -512
  174. package/ai-config/skills/database/redis-cache/SKILL.md +0 -343
  175. package/ai-config/skills/database/sqlite-embedded/SKILL.md +0 -388
  176. package/ai-config/skills/database/timescaledb/SKILL.md +0 -320
  177. package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
  178. package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
  179. package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
  180. package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
  181. package/ai-config/skills/frontend/astro-ssr/SKILL.md +0 -441
  182. package/ai-config/skills/frontend/frontend-design/SKILL.md +0 -54
  183. package/ai-config/skills/frontend/frontend-web/SKILL.md +0 -368
  184. package/ai-config/skills/frontend/mantine-ui/SKILL.md +0 -396
  185. package/ai-config/skills/frontend/tanstack-query/SKILL.md +0 -439
  186. package/ai-config/skills/frontend/zod-validation/SKILL.md +0 -417
  187. package/ai-config/skills/frontend/zustand-state/SKILL.md +0 -350
  188. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +0 -244
  189. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +0 -378
  190. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +0 -435
  191. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +0 -420
  192. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +0 -456
  193. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +0 -546
  194. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +0 -474
  195. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +0 -315
  196. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +0 -504
  197. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +0 -448
  198. package/ai-config/skills/prompt-improver/SKILL.md +0 -125
  199. package/ai-config/skills/quality/ghagga-review/SKILL.md +0 -216
  200. package/ai-config/skills/references/hooks-patterns/SKILL.md +0 -238
  201. package/ai-config/skills/references/mcp-servers/SKILL.md +0 -275
  202. package/ai-config/skills/references/plugins-reference/SKILL.md +0 -110
  203. package/ai-config/skills/references/skills-reference/SKILL.md +0 -420
  204. package/ai-config/skills/references/subagent-templates/SKILL.md +0 -193
  205. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +0 -410
  206. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +0 -408
  207. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +0 -386
  208. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +0 -324
  209. package/ai-config/skills/testing/playwright-e2e/SKILL.md +0 -289
  210. package/ai-config/skills/testing/testcontainers/SKILL.md +0 -299
  211. package/ai-config/skills/testing/vitest-testing/SKILL.md +0 -381
  212. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +0 -118
  213. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +0 -299
  214. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +0 -158
  215. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +0 -117
  216. package/ai-config/skills/workflow/git-github/SKILL.md +0 -334
  217. package/ai-config/skills/workflow/git-github/references/examples.md +0 -160
  218. package/ai-config/skills/workflow/git-workflow/SKILL.md +0 -214
  219. package/ai-config/skills/workflow/ide-plugins/SKILL.md +0 -277
  220. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +0 -401
  221. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +0 -199
  222. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +0 -100
  223. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +0 -73
  224. package/ai-config/skills/workflow/wave-workflow/SKILL.md +0 -178
  225. package/schemas/agent.schema.json +0 -34
  226. package/schemas/ai-config.schema.json +0 -28
  227. package/schemas/plugin.schema.json +0 -62
  228. package/schemas/skill.schema.json +0 -44
@@ -1,410 +0,0 @@
1
- ---
2
- name: modbus-protocol
3
- description: >
4
- Modbus industrial protocol implementation in Rust, Go, and Python.
5
- Trigger: modbus, plc, scada, industrial protocol, registers, coils
6
- tools:
7
- - Read
8
- - Write
9
- - Bash
10
- - Grep
11
- metadata:
12
- author: plataforma-industrial
13
- version: "2.0"
14
- tags: [industrial, modbus, plc, sensors, protocol]
15
- language: rust
16
- updated: "2026-02"
17
- ---
18
-
19
- # Modbus Protocol
20
-
21
- > Industrial Modbus TCP/RTU implementation for sensor communication
22
-
23
- ## When to Use
24
-
25
- - [ ] Reading data from PLCs (Siemens, Allen-Bradley, Schneider)
26
- - [ ] Communicating with industrial sensors
27
- - [ ] Building SCADA/gateway systems
28
- - [ ] Implementing OT (Operational Technology) integrations
29
-
30
- ## Stack
31
-
32
- ```yaml
33
- # Rust
34
- tokio-modbus: "0.13+"
35
-
36
- # Go
37
- github.com/simonvetter/modbus: latest
38
-
39
- # Python
40
- pymodbus: "3.6+"
41
- ```
42
-
43
- ## Modbus Fundamentals
44
-
45
- ### Register Types
46
-
47
- | Type | Address Range | Access | Use Case |
48
- |------|---------------|--------|----------|
49
- | Coils | 00001-09999 | R/W | Digital outputs (on/off) |
50
- | Discrete Inputs | 10001-19999 | R | Digital inputs (read-only) |
51
- | Input Registers | 30001-39999 | R | Analog inputs (16-bit) |
52
- | Holding Registers | 40001-49999 | R/W | Configuration & data |
53
-
54
- ### Function Codes
55
-
56
- | Code | Function | Description |
57
- |------|----------|-------------|
58
- | 01 | Read Coils | Read multiple digital outputs |
59
- | 02 | Read Discrete Inputs | Read digital inputs |
60
- | 03 | Read Holding Registers | Read configuration registers |
61
- | 04 | Read Input Registers | Read analog inputs |
62
- | 05 | Write Single Coil | Set single output |
63
- | 06 | Write Single Register | Write one register |
64
- | 16 | Write Multiple Registers | Write block of registers |
65
-
66
- ## Rust Implementation
67
-
68
- ### Client Setup
69
-
70
- ```rust
71
- use tokio_modbus::prelude::*;
72
- use tokio_modbus::client::tcp;
73
- use std::net::SocketAddr;
74
- use tokio::time::{timeout, Duration};
75
-
76
- pub struct ModbusClient {
77
- ctx: client::Context,
78
- timeout_duration: Duration,
79
- }
80
-
81
- impl ModbusClient {
82
- pub async fn connect(addr: SocketAddr, slave_id: u8) -> Result<Self, ModbusError> {
83
- let ctx = tcp::connect_slave(addr, Slave(slave_id)).await?;
84
- Ok(Self { ctx, timeout_duration: Duration::from_secs(5) })
85
- }
86
-
87
- pub async fn read_holding_registers(&mut self, address: u16, count: u16) -> Result<Vec<u16>> {
88
- timeout(self.timeout_duration, self.ctx.read_holding_registers(address, count))
89
- .await
90
- .map_err(|_| ModbusError::Timeout)?
91
- .map_err(ModbusError::from)
92
- }
93
-
94
- pub async fn write_single_register(&mut self, address: u16, value: u16) -> Result<()> {
95
- timeout(self.timeout_duration, self.ctx.write_single_register(address, value))
96
- .await
97
- .map_err(|_| ModbusError::Timeout)?
98
- .map_err(ModbusError::from)
99
- }
100
- }
101
- ```
102
-
103
- ### Data Type Conversions
104
-
105
- ```rust
106
- /// Two 16-bit registers to f32 (big-endian)
107
- pub fn registers_to_f32(regs: &[u16]) -> f32 {
108
- let bytes = [
109
- (regs[0] >> 8) as u8, regs[0] as u8,
110
- (regs[1] >> 8) as u8, regs[1] as u8,
111
- ];
112
- f32::from_be_bytes(bytes)
113
- }
114
-
115
- /// Two 16-bit registers to f32 (little-endian, swapped)
116
- pub fn registers_to_f32_le(regs: &[u16]) -> f32 {
117
- let bytes = [
118
- regs[1] as u8, (regs[1] >> 8) as u8,
119
- regs[0] as u8, (regs[0] >> 8) as u8,
120
- ];
121
- f32::from_le_bytes(bytes)
122
- }
123
-
124
- /// f32 to two 16-bit registers
125
- pub fn f32_to_registers(value: f32) -> [u16; 2] {
126
- let bytes = value.to_be_bytes();
127
- [
128
- ((bytes[0] as u16) << 8) | (bytes[1] as u16),
129
- ((bytes[2] as u16) << 8) | (bytes[3] as u16),
130
- ]
131
- }
132
-
133
- /// Scale raw value to engineering units
134
- pub fn scale_value(raw: u16, min_raw: u16, max_raw: u16, min_eng: f32, max_eng: f32) -> f32 {
135
- let range_raw = (max_raw - min_raw) as f32;
136
- let range_eng = max_eng - min_eng;
137
- let normalized = (raw - min_raw) as f32 / range_raw;
138
- min_eng + (normalized * range_eng)
139
- }
140
- ```
141
-
142
- ### Sensor Reader
143
-
144
- ```rust
145
- #[derive(Debug, Clone)]
146
- pub struct SensorConfig {
147
- pub id: String,
148
- pub name: String,
149
- pub address: u16,
150
- pub data_type: DataType,
151
- pub unit: String,
152
- pub scale: Option<Scale>,
153
- }
154
-
155
- #[derive(Debug, Clone)]
156
- pub enum DataType {
157
- UInt16,
158
- Int16,
159
- Float32,
160
- Float32LE,
161
- }
162
-
163
- #[derive(Debug, Clone)]
164
- pub struct SensorReading {
165
- pub sensor_id: String,
166
- pub value: f64,
167
- pub quality: u8, // 192=Good, 128=Uncertain, 0=Bad
168
- pub timestamp: i64,
169
- }
170
-
171
- pub struct SensorReader {
172
- client: ModbusClient,
173
- sensors: Vec<SensorConfig>,
174
- }
175
-
176
- impl SensorReader {
177
- pub async fn read_sensor(&mut self, sensor: &SensorConfig) -> Result<SensorReading> {
178
- let count = match sensor.data_type {
179
- DataType::UInt16 | DataType::Int16 => 1,
180
- DataType::Float32 | DataType::Float32LE => 2,
181
- };
182
-
183
- let registers = self.client.read_holding_registers(sensor.address, count).await?;
184
-
185
- let raw_value: f64 = match sensor.data_type {
186
- DataType::UInt16 => registers[0] as f64,
187
- DataType::Int16 => (registers[0] as i16) as f64,
188
- DataType::Float32 => registers_to_f32(&registers) as f64,
189
- DataType::Float32LE => registers_to_f32_le(&registers) as f64,
190
- };
191
-
192
- let value = if let Some(scale) = &sensor.scale {
193
- scale_value(raw_value as u16, scale.min_raw, scale.max_raw, scale.min_eng, scale.max_eng) as f64
194
- } else {
195
- raw_value
196
- };
197
-
198
- Ok(SensorReading {
199
- sensor_id: sensor.id.clone(),
200
- value,
201
- quality: 192, // Good
202
- timestamp: chrono::Utc::now().timestamp_millis(),
203
- })
204
- }
205
- }
206
- ```
207
-
208
- ## Go Implementation
209
-
210
- ```go
211
- package modbus
212
-
213
- import (
214
- "encoding/binary"
215
- "math"
216
- "sync"
217
- "time"
218
-
219
- "github.com/simonvetter/modbus"
220
- )
221
-
222
- type Client struct {
223
- client *modbus.ModbusClient
224
- mu sync.Mutex
225
- }
226
-
227
- func NewClient(address string, slaveID uint8) (*Client, error) {
228
- client, err := modbus.NewClient(&modbus.ClientConfiguration{
229
- URL: fmt.Sprintf("tcp://%s", address),
230
- Speed: 19200,
231
- Timeout: 5 * time.Second,
232
- })
233
- if err != nil { return nil, err }
234
-
235
- if err := client.Open(); err != nil { return nil, err }
236
- client.SetUnitId(slaveID)
237
-
238
- return &Client{client: client}, nil
239
- }
240
-
241
- func (c *Client) ReadHoldingRegisters(address, count uint16) ([]uint16, error) {
242
- c.mu.Lock()
243
- defer c.mu.Unlock()
244
- return c.client.ReadRegisters(address, count, modbus.HOLDING_REGISTER)
245
- }
246
-
247
- func RegistersToFloat32(regs []uint16) float32 {
248
- bytes := make([]byte, 4)
249
- binary.BigEndian.PutUint16(bytes[0:2], regs[0])
250
- binary.BigEndian.PutUint16(bytes[2:4], regs[1])
251
- return math.Float32frombits(binary.BigEndian.Uint32(bytes))
252
- }
253
- ```
254
-
255
- ## Python Implementation
256
-
257
- ```python
258
- from pymodbus.client import AsyncModbusTcpClient
259
- from dataclasses import dataclass
260
- import struct
261
-
262
- @dataclass
263
- class SensorConfig:
264
- id: str
265
- address: int
266
- data_type: str # 'uint16', 'int16', 'float32'
267
- unit: str
268
-
269
- class ModbusReader:
270
- def __init__(self, host: str, port: int = 502, slave_id: int = 1):
271
- self.host = host
272
- self.port = port
273
- self.slave_id = slave_id
274
-
275
- async def connect(self):
276
- self.client = AsyncModbusTcpClient(self.host, port=self.port)
277
- await self.client.connect()
278
-
279
- async def read_holding_registers(self, address: int, count: int):
280
- result = await self.client.read_holding_registers(address, count, slave=self.slave_id)
281
- return result.registers
282
-
283
- async def read_sensor(self, config: SensorConfig) -> float:
284
- count = 2 if 'float32' in config.data_type else 1
285
- regs = await self.read_holding_registers(config.address, count)
286
-
287
- if config.data_type == 'uint16':
288
- return regs[0]
289
- elif config.data_type == 'int16':
290
- return struct.unpack('>h', struct.pack('>H', regs[0]))[0]
291
- elif config.data_type == 'float32':
292
- bytes_data = struct.pack('>HH', regs[0], regs[1])
293
- return struct.unpack('>f', bytes_data)[0]
294
- ```
295
-
296
- ## PLC Address Maps
297
-
298
- ### Siemens S7-1200/1500
299
-
300
- ```yaml
301
- holding_registers:
302
- 40001: DB1.DBD0 # Float, first double word in DB1
303
- 40003: DB1.DBD4 # Float, second double word
304
- 40005: MW100 # Word memory
305
-
306
- coils:
307
- 00001: Q0.0 # Output bit 0.0
308
- 00002: Q0.1 # Output bit 0.1
309
- ```
310
-
311
- ### Allen-Bradley ControlLogix
312
-
313
- ```yaml
314
- holding_registers:
315
- 40001: N7:0 # Integer file
316
- 40002: F8:0 # Float (uses 2 registers)
317
- ```
318
-
319
- ### Schneider Modicon
320
-
321
- ```yaml
322
- holding_registers:
323
- 40001: %MW0 # Memory word 0
324
- 40003: %MF0 # Float (2 registers)
325
- ```
326
-
327
- ## Error Handling
328
-
329
- ```rust
330
- pub fn modbus_error_description(code: u8) -> &'static str {
331
- match code {
332
- 0x01 => "Illegal Function",
333
- 0x02 => "Illegal Data Address",
334
- 0x03 => "Illegal Data Value",
335
- 0x04 => "Slave Device Failure",
336
- 0x05 => "Acknowledge",
337
- 0x06 => "Slave Device Busy",
338
- _ => "Unknown Error",
339
- }
340
- }
341
- ```
342
-
343
- ## Best Practices
344
-
345
- ### Batch Reads
346
-
347
- ```rust
348
- // ✅ Single read for contiguous registers
349
- client.read_holding_registers(40001, 10).await?;
350
-
351
- // ❌ Multiple individual reads - slow!
352
- for addr in 40001..40011 {
353
- client.read_holding_registers(addr, 1).await?;
354
- }
355
- ```
356
-
357
- ### Connection Reuse
358
-
359
- ```rust
360
- // ✅ Reuse connection
361
- let client = ModbusClient::connect(addr, slave_id).await?;
362
- for _ in 0..100 {
363
- client.read_holding_registers(addr, count).await?;
364
- }
365
-
366
- // ❌ New connection per read
367
- for _ in 0..100 {
368
- let client = ModbusClient::connect(addr, slave_id).await?;
369
- client.read_holding_registers(addr, count).await?;
370
- }
371
- ```
372
-
373
- ### Polling Intervals
374
-
375
- | Sensor Type | Recommended Interval |
376
- |-------------|---------------------|
377
- | Vibration | 10-50ms |
378
- | Temperature/Pressure | 500ms-1s |
379
- | Level/Flow totals | 5-10s |
380
-
381
- ## Quick Reference
382
-
383
- | Task | Rust |
384
- |------|------|
385
- | Read holding | `ctx.read_holding_registers(addr, count).await` |
386
- | Read input | `ctx.read_input_registers(addr, count).await` |
387
- | Write single | `ctx.write_single_register(addr, value).await` |
388
- | Write multiple | `ctx.write_multiple_registers(addr, &values).await` |
389
- | Read coils | `ctx.read_coils(addr, count).await` |
390
-
391
- ## Quality Codes (OPC UA)
392
-
393
- | Code | Meaning |
394
- |------|---------|
395
- | 192 (0xC0) | Good |
396
- | 128 (0x80) | Uncertain |
397
- | 0 (0x00) | Bad |
398
-
399
- ## Resources
400
-
401
- - [Modbus Specification](https://modbus.org/specs.php)
402
- - [tokio-modbus Docs](https://docs.rs/tokio-modbus)
403
- - [pymodbus Documentation](https://pymodbus.readthedocs.io/)
404
-
405
- ## Related Skills
406
-
407
- - `mqtt-rumqttc`: Data forwarding to MQTT
408
- - `tokio-async`: Async polling patterns
409
- - `timescaledb`: Industrial data storage
410
- - `rust-systems`: Full Rust integration