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.
- package/ci-local/ci-local.sh +20 -8
- package/package.json +1 -1
- package/ai-config/.skillignore +0 -15
- package/ai-config/AUTO_INVOKE.md +0 -300
- package/ai-config/agents/_TEMPLATE.md +0 -93
- package/ai-config/agents/business/api-designer.md +0 -1657
- package/ai-config/agents/business/business-analyst.md +0 -1331
- package/ai-config/agents/business/product-strategist.md +0 -206
- package/ai-config/agents/business/project-manager.md +0 -178
- package/ai-config/agents/business/requirements-analyst.md +0 -1277
- package/ai-config/agents/business/technical-writer.md +0 -1679
- package/ai-config/agents/creative/ux-designer.md +0 -205
- package/ai-config/agents/data-ai/ai-engineer.md +0 -487
- package/ai-config/agents/data-ai/analytics-engineer.md +0 -953
- package/ai-config/agents/data-ai/data-engineer.md +0 -173
- package/ai-config/agents/data-ai/data-scientist.md +0 -672
- package/ai-config/agents/data-ai/mlops-engineer.md +0 -814
- package/ai-config/agents/data-ai/prompt-engineer.md +0 -772
- package/ai-config/agents/development/angular-expert.md +0 -620
- package/ai-config/agents/development/backend-architect.md +0 -795
- package/ai-config/agents/development/database-specialist.md +0 -212
- package/ai-config/agents/development/frontend-specialist.md +0 -686
- package/ai-config/agents/development/fullstack-engineer.md +0 -668
- package/ai-config/agents/development/golang-pro.md +0 -338
- package/ai-config/agents/development/java-enterprise.md +0 -400
- package/ai-config/agents/development/javascript-pro.md +0 -422
- package/ai-config/agents/development/nextjs-pro.md +0 -474
- package/ai-config/agents/development/python-pro.md +0 -570
- package/ai-config/agents/development/react-pro.md +0 -487
- package/ai-config/agents/development/rust-pro.md +0 -246
- package/ai-config/agents/development/spring-boot-4-expert.md +0 -326
- package/ai-config/agents/development/typescript-pro.md +0 -336
- package/ai-config/agents/development/vue-specialist.md +0 -605
- package/ai-config/agents/infrastructure/cloud-architect.md +0 -472
- package/ai-config/agents/infrastructure/deployment-manager.md +0 -358
- package/ai-config/agents/infrastructure/devops-engineer.md +0 -455
- package/ai-config/agents/infrastructure/incident-responder.md +0 -519
- package/ai-config/agents/infrastructure/kubernetes-expert.md +0 -705
- package/ai-config/agents/infrastructure/monitoring-specialist.md +0 -674
- package/ai-config/agents/infrastructure/performance-engineer.md +0 -658
- package/ai-config/agents/orchestrator.md +0 -241
- package/ai-config/agents/quality/accessibility-auditor.md +0 -1204
- package/ai-config/agents/quality/code-reviewer-compact.md +0 -123
- package/ai-config/agents/quality/code-reviewer.md +0 -363
- package/ai-config/agents/quality/dependency-manager.md +0 -743
- package/ai-config/agents/quality/e2e-test-specialist.md +0 -1005
- package/ai-config/agents/quality/performance-tester.md +0 -1086
- package/ai-config/agents/quality/security-auditor.md +0 -133
- package/ai-config/agents/quality/test-engineer.md +0 -453
- package/ai-config/agents/specialists/api-designer.md +0 -87
- package/ai-config/agents/specialists/backend-architect.md +0 -73
- package/ai-config/agents/specialists/code-reviewer.md +0 -77
- package/ai-config/agents/specialists/db-optimizer.md +0 -75
- package/ai-config/agents/specialists/devops-engineer.md +0 -83
- package/ai-config/agents/specialists/documentation-writer.md +0 -78
- package/ai-config/agents/specialists/frontend-developer.md +0 -75
- package/ai-config/agents/specialists/performance-analyst.md +0 -82
- package/ai-config/agents/specialists/refactor-specialist.md +0 -74
- package/ai-config/agents/specialists/security-auditor.md +0 -74
- package/ai-config/agents/specialists/test-engineer.md +0 -81
- package/ai-config/agents/specialists/ux-consultant.md +0 -76
- package/ai-config/agents/specialized/agent-generator.md +0 -1190
- package/ai-config/agents/specialized/blockchain-developer.md +0 -149
- package/ai-config/agents/specialized/code-migrator.md +0 -892
- package/ai-config/agents/specialized/context-manager.md +0 -978
- package/ai-config/agents/specialized/documentation-writer.md +0 -1078
- package/ai-config/agents/specialized/ecommerce-expert.md +0 -1756
- package/ai-config/agents/specialized/embedded-engineer.md +0 -1714
- package/ai-config/agents/specialized/error-detective.md +0 -1034
- package/ai-config/agents/specialized/fintech-specialist.md +0 -1659
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +0 -1988
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +0 -2136
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +0 -4503
- package/ai-config/agents/specialized/freelance-project-planner.md +0 -722
- package/ai-config/agents/specialized/game-developer.md +0 -1963
- package/ai-config/agents/specialized/healthcare-dev.md +0 -1620
- package/ai-config/agents/specialized/mobile-developer.md +0 -188
- package/ai-config/agents/specialized/parallel-plan-executor.md +0 -506
- package/ai-config/agents/specialized/plan-executor.md +0 -485
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +0 -485
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +0 -3493
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +0 -778
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +0 -918
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +0 -1537
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +0 -2633
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +0 -5610
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +0 -335
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +0 -215
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +0 -260
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +0 -379
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +0 -355
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +0 -279
- package/ai-config/agents/specialized/template-writer.md +0 -347
- package/ai-config/agents/specialized/test-runner.md +0 -99
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +0 -244
- package/ai-config/agents/specialized/wave-executor.md +0 -138
- package/ai-config/agents/specialized/workflow-optimizer.md +0 -1114
- package/ai-config/commands/git/changelog.md +0 -32
- package/ai-config/commands/git/ci-local.md +0 -70
- package/ai-config/commands/git/commit.md +0 -35
- package/ai-config/commands/git/fix-issue.md +0 -23
- package/ai-config/commands/git/pr-create.md +0 -42
- package/ai-config/commands/git/pr-review.md +0 -50
- package/ai-config/commands/git/worktree.md +0 -39
- package/ai-config/commands/refactoring/cleanup.md +0 -24
- package/ai-config/commands/refactoring/dead-code.md +0 -40
- package/ai-config/commands/refactoring/extract.md +0 -31
- package/ai-config/commands/testing/e2e.md +0 -30
- package/ai-config/commands/testing/tdd.md +0 -36
- package/ai-config/commands/testing/test-coverage.md +0 -30
- package/ai-config/commands/testing/test-fix.md +0 -24
- package/ai-config/commands/workflow/generate-agents-md.md +0 -85
- package/ai-config/commands/workflow/planning.md +0 -47
- package/ai-config/commands/workflows/compound.md +0 -89
- package/ai-config/commands/workflows/diagnose.md +0 -70
- package/ai-config/commands/workflows/discover.md +0 -86
- package/ai-config/commands/workflows/plan.md +0 -77
- package/ai-config/commands/workflows/review.md +0 -78
- package/ai-config/commands/workflows/work.md +0 -75
- package/ai-config/config.yaml +0 -18
- package/ai-config/hooks/_TEMPLATE.md +0 -96
- package/ai-config/hooks/block-dangerous-commands.md +0 -75
- package/ai-config/hooks/commit-guard.md +0 -90
- package/ai-config/hooks/context-loader.md +0 -73
- package/ai-config/hooks/improve-prompt.md +0 -91
- package/ai-config/hooks/learning-log.md +0 -72
- package/ai-config/hooks/model-router.md +0 -86
- package/ai-config/hooks/secret-scanner.md +0 -64
- package/ai-config/hooks/skill-validator.md +0 -102
- package/ai-config/hooks/task-artifact.md +0 -114
- package/ai-config/hooks/validate-workflow.md +0 -100
- package/ai-config/prompts/base.md +0 -71
- package/ai-config/prompts/modes/debug.md +0 -34
- package/ai-config/prompts/modes/deploy.md +0 -40
- package/ai-config/prompts/modes/research.md +0 -32
- package/ai-config/prompts/modes/review.md +0 -33
- package/ai-config/prompts/review-policy.md +0 -79
- package/ai-config/skills/_TEMPLATE.md +0 -157
- package/ai-config/skills/backend/api-gateway/SKILL.md +0 -254
- package/ai-config/skills/backend/bff-concepts/SKILL.md +0 -239
- package/ai-config/skills/backend/bff-spring/SKILL.md +0 -364
- package/ai-config/skills/backend/chi-router/SKILL.md +0 -396
- package/ai-config/skills/backend/error-handling/SKILL.md +0 -255
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +0 -323
- package/ai-config/skills/backend/fastapi/SKILL.md +0 -302
- package/ai-config/skills/backend/gateway-spring/SKILL.md +0 -390
- package/ai-config/skills/backend/go-backend/SKILL.md +0 -457
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +0 -274
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +0 -352
- package/ai-config/skills/backend/graphql-spring/SKILL.md +0 -398
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +0 -283
- package/ai-config/skills/backend/grpc-spring/SKILL.md +0 -445
- package/ai-config/skills/backend/jwt-auth/SKILL.md +0 -412
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +0 -259
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +0 -261
- package/ai-config/skills/backend/search-concepts/SKILL.md +0 -263
- package/ai-config/skills/backend/search-spring/SKILL.md +0 -375
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +0 -172
- package/ai-config/skills/backend/websockets/SKILL.md +0 -532
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +0 -423
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +0 -195
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +0 -340
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +0 -440
- package/ai-config/skills/data-ai/langchain/SKILL.md +0 -238
- package/ai-config/skills/data-ai/mlflow/SKILL.md +0 -302
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +0 -290
- package/ai-config/skills/data-ai/powerbi/SKILL.md +0 -352
- package/ai-config/skills/data-ai/pytorch/SKILL.md +0 -274
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +0 -321
- package/ai-config/skills/data-ai/vector-db/SKILL.md +0 -301
- package/ai-config/skills/database/graph-databases/SKILL.md +0 -218
- package/ai-config/skills/database/graph-spring/SKILL.md +0 -361
- package/ai-config/skills/database/pgx-postgres/SKILL.md +0 -512
- package/ai-config/skills/database/redis-cache/SKILL.md +0 -343
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +0 -388
- package/ai-config/skills/database/timescaledb/SKILL.md +0 -320
- package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
- package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
- package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
- package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +0 -441
- package/ai-config/skills/frontend/frontend-design/SKILL.md +0 -54
- package/ai-config/skills/frontend/frontend-web/SKILL.md +0 -368
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +0 -396
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +0 -439
- package/ai-config/skills/frontend/zod-validation/SKILL.md +0 -417
- package/ai-config/skills/frontend/zustand-state/SKILL.md +0 -350
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +0 -244
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +0 -378
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +0 -435
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +0 -420
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +0 -456
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +0 -546
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +0 -474
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +0 -315
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +0 -504
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +0 -448
- package/ai-config/skills/prompt-improver/SKILL.md +0 -125
- package/ai-config/skills/quality/ghagga-review/SKILL.md +0 -216
- package/ai-config/skills/references/hooks-patterns/SKILL.md +0 -238
- package/ai-config/skills/references/mcp-servers/SKILL.md +0 -275
- package/ai-config/skills/references/plugins-reference/SKILL.md +0 -110
- package/ai-config/skills/references/skills-reference/SKILL.md +0 -420
- package/ai-config/skills/references/subagent-templates/SKILL.md +0 -193
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +0 -410
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +0 -408
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +0 -386
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +0 -324
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +0 -289
- package/ai-config/skills/testing/testcontainers/SKILL.md +0 -299
- package/ai-config/skills/testing/vitest-testing/SKILL.md +0 -381
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +0 -118
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +0 -299
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +0 -158
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +0 -117
- package/ai-config/skills/workflow/git-github/SKILL.md +0 -334
- package/ai-config/skills/workflow/git-github/references/examples.md +0 -160
- package/ai-config/skills/workflow/git-workflow/SKILL.md +0 -214
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +0 -277
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +0 -401
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +0 -199
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +0 -100
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +0 -73
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +0 -178
- package/schemas/agent.schema.json +0 -34
- package/schemas/ai-config.schema.json +0 -28
- package/schemas/plugin.schema.json +0 -62
- package/schemas/skill.schema.json +0 -44
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: mqtt-rumqttc
|
|
3
|
-
description: >
|
|
4
|
-
MQTT client patterns for Rust using rumqttc - pub/sub, QoS, event handling.
|
|
5
|
-
Trigger: mqtt, rumqttc, publish, subscribe, broker, iot messaging
|
|
6
|
-
tools:
|
|
7
|
-
- Read
|
|
8
|
-
- Write
|
|
9
|
-
- Bash
|
|
10
|
-
- Grep
|
|
11
|
-
metadata:
|
|
12
|
-
author: plataforma-industrial
|
|
13
|
-
version: "2.0"
|
|
14
|
-
tags: [rust, mqtt, messaging, iot, pubsub]
|
|
15
|
-
language: rust
|
|
16
|
-
updated: "2026-02"
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
# MQTT with rumqttc
|
|
20
|
-
|
|
21
|
-
> MQTT client patterns for IoT and industrial messaging in Rust
|
|
22
|
-
|
|
23
|
-
## When to Use
|
|
24
|
-
|
|
25
|
-
- [ ] Building IoT/industrial messaging systems
|
|
26
|
-
- [ ] Publishing sensor data to MQTT brokers
|
|
27
|
-
- [ ] Subscribing to real-time data streams
|
|
28
|
-
- [ ] Implementing pub/sub patterns in Rust
|
|
29
|
-
|
|
30
|
-
## Stack
|
|
31
|
-
|
|
32
|
-
```toml
|
|
33
|
-
[dependencies]
|
|
34
|
-
rumqttc = "0.24"
|
|
35
|
-
tokio = { version = "1.36", features = ["full"] }
|
|
36
|
-
serde = { version = "1.0", features = ["derive"] }
|
|
37
|
-
serde_json = "1.0"
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Critical Patterns
|
|
41
|
-
|
|
42
|
-
### Pattern 1: Client Setup
|
|
43
|
-
|
|
44
|
-
```rust
|
|
45
|
-
use rumqttc::{AsyncClient, MqttOptions, QoS, EventLoop};
|
|
46
|
-
use std::time::Duration;
|
|
47
|
-
|
|
48
|
-
pub struct MqttClient {
|
|
49
|
-
client: AsyncClient,
|
|
50
|
-
event_loop: EventLoop,
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
impl MqttClient {
|
|
54
|
-
pub fn new(config: &MqttConfig) -> Self {
|
|
55
|
-
let mut options = MqttOptions::new(
|
|
56
|
-
&config.client_id,
|
|
57
|
-
&config.host,
|
|
58
|
-
config.port,
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
options.set_keep_alive(Duration::from_secs(30));
|
|
62
|
-
options.set_clean_session(true);
|
|
63
|
-
|
|
64
|
-
// Optional credentials
|
|
65
|
-
if let (Some(user), Some(pass)) = (&config.username, &config.password) {
|
|
66
|
-
options.set_credentials(user, pass);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let (client, event_loop) = AsyncClient::new(options, 100);
|
|
70
|
-
Self { client, event_loop }
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Pattern 2: Last Will Testament (LWT)
|
|
76
|
-
|
|
77
|
-
```rust
|
|
78
|
-
use rumqttc::LastWill;
|
|
79
|
-
|
|
80
|
-
// LWT - broker publishes when client disconnects unexpectedly
|
|
81
|
-
options.set_last_will(LastWill::new(
|
|
82
|
-
"system/gateway/status",
|
|
83
|
-
"offline",
|
|
84
|
-
QoS::AtLeastOnce,
|
|
85
|
-
true, // retained
|
|
86
|
-
));
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Pattern 3: QoS Selection
|
|
90
|
-
|
|
91
|
-
```rust
|
|
92
|
-
// QoS 0: At most once - fire and forget (fastest)
|
|
93
|
-
client.publish("sensors/temp/reading", QoS::AtMostOnce, false, payload).await?;
|
|
94
|
-
|
|
95
|
-
// QoS 1: At least once - confirmed delivery (recommended default)
|
|
96
|
-
client.publish("alerts/critical", QoS::AtLeastOnce, false, payload).await?;
|
|
97
|
-
|
|
98
|
-
// QoS 2: Exactly once - guaranteed delivery (highest overhead)
|
|
99
|
-
client.publish("commands/shutdown", QoS::ExactlyOnce, false, payload).await?;
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Publishing
|
|
103
|
-
|
|
104
|
-
### Basic Publish
|
|
105
|
-
|
|
106
|
-
```rust
|
|
107
|
-
impl MqttClient {
|
|
108
|
-
pub async fn publish(&self, topic: &str, payload: &[u8]) -> Result<()> {
|
|
109
|
-
self.client
|
|
110
|
-
.publish(topic, QoS::AtLeastOnce, false, payload)
|
|
111
|
-
.await
|
|
112
|
-
.map_err(|e| Error::Mqtt(e.to_string()))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
pub async fn publish_json<T: serde::Serialize>(&self, topic: &str, data: &T) -> Result<()> {
|
|
116
|
-
let payload = serde_json::to_vec(data)?;
|
|
117
|
-
self.publish(topic, &payload).await
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Retained - new subscribers get last value immediately
|
|
121
|
-
pub async fn publish_retained(&self, topic: &str, payload: &[u8]) -> Result<()> {
|
|
122
|
-
self.client
|
|
123
|
-
.publish(topic, QoS::AtLeastOnce, true, payload)
|
|
124
|
-
.await
|
|
125
|
-
.map_err(|e| Error::Mqtt(e.to_string()))
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Sensor Publisher
|
|
131
|
-
|
|
132
|
-
```rust
|
|
133
|
-
use serde::Serialize;
|
|
134
|
-
|
|
135
|
-
#[derive(Debug, Serialize)]
|
|
136
|
-
pub struct SensorReading {
|
|
137
|
-
pub sensor_id: String,
|
|
138
|
-
pub value: f64,
|
|
139
|
-
pub unit: String,
|
|
140
|
-
pub timestamp: i64,
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
pub struct SensorPublisher {
|
|
144
|
-
client: AsyncClient,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
impl SensorPublisher {
|
|
148
|
-
pub async fn publish_reading(&self, reading: &SensorReading) -> Result<()> {
|
|
149
|
-
let topic = format!("sensors/{}/reading", reading.sensor_id);
|
|
150
|
-
let payload = serde_json::to_vec(reading)?;
|
|
151
|
-
|
|
152
|
-
self.client
|
|
153
|
-
.publish(&topic, QoS::AtLeastOnce, false, payload)
|
|
154
|
-
.await?;
|
|
155
|
-
Ok(())
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Status should be retained
|
|
159
|
-
pub async fn publish_status(&self, sensor_id: &str, status: &str) -> Result<()> {
|
|
160
|
-
let topic = format!("sensors/{}/status", sensor_id);
|
|
161
|
-
self.client
|
|
162
|
-
.publish(&topic, QoS::AtLeastOnce, true, status.as_bytes())
|
|
163
|
-
.await?;
|
|
164
|
-
Ok(())
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
## Subscribing
|
|
170
|
-
|
|
171
|
-
### Topic Patterns
|
|
172
|
-
|
|
173
|
-
```rust
|
|
174
|
-
// Single level wildcard (+)
|
|
175
|
-
const SENSOR_READINGS: &str = "sensors/+/reading"; // sensors/temp-1/reading, sensors/pressure-2/reading
|
|
176
|
-
const SENSOR_STATUS: &str = "sensors/+/status";
|
|
177
|
-
|
|
178
|
-
// Multi-level wildcard (#)
|
|
179
|
-
const ALL_ALERTS: &str = "alerts/#"; // alerts/critical, alerts/warning/temp-1
|
|
180
|
-
const ALL_SYSTEM: &str = "system/#";
|
|
181
|
-
|
|
182
|
-
// Exact topic
|
|
183
|
-
const GATEWAY_COMMAND: &str = "system/gateway/command";
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Event Loop Processing
|
|
187
|
-
|
|
188
|
-
```rust
|
|
189
|
-
use rumqttc::{Event, Packet};
|
|
190
|
-
|
|
191
|
-
pub async fn run_event_loop(mut event_loop: EventLoop) {
|
|
192
|
-
loop {
|
|
193
|
-
match event_loop.poll().await {
|
|
194
|
-
Ok(Event::Incoming(Packet::Publish(publish))) => {
|
|
195
|
-
let topic = publish.topic.as_str();
|
|
196
|
-
let payload = &publish.payload;
|
|
197
|
-
handle_message(topic, payload).await;
|
|
198
|
-
}
|
|
199
|
-
Ok(Event::Incoming(Packet::ConnAck(_))) => {
|
|
200
|
-
tracing::info!("Connected to MQTT broker");
|
|
201
|
-
}
|
|
202
|
-
Ok(Event::Incoming(Packet::SubAck(_))) => {
|
|
203
|
-
tracing::debug!("Subscription acknowledged");
|
|
204
|
-
}
|
|
205
|
-
Err(e) => {
|
|
206
|
-
tracing::error!("MQTT error: {}", e);
|
|
207
|
-
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
208
|
-
}
|
|
209
|
-
_ => {}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Complete Service Pattern
|
|
216
|
-
|
|
217
|
-
```rust
|
|
218
|
-
use tokio::sync::{broadcast, mpsc};
|
|
219
|
-
|
|
220
|
-
pub struct MqttService {
|
|
221
|
-
client: AsyncClient,
|
|
222
|
-
shutdown_rx: broadcast::Receiver<()>,
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
impl MqttService {
|
|
226
|
-
pub async fn run(mut self, mut event_loop: EventLoop) -> Result<()> {
|
|
227
|
-
// Subscribe to topics
|
|
228
|
-
self.client.subscribe("commands/#", QoS::AtLeastOnce).await?;
|
|
229
|
-
self.client.subscribe("config/+", QoS::AtLeastOnce).await?;
|
|
230
|
-
|
|
231
|
-
loop {
|
|
232
|
-
tokio::select! {
|
|
233
|
-
event = event_loop.poll() => {
|
|
234
|
-
match event {
|
|
235
|
-
Ok(Event::Incoming(Packet::Publish(p))) => {
|
|
236
|
-
self.handle_publish(p).await?;
|
|
237
|
-
}
|
|
238
|
-
Ok(Event::Incoming(Packet::ConnAck(_))) => {
|
|
239
|
-
self.on_connect().await?;
|
|
240
|
-
}
|
|
241
|
-
Err(e) => {
|
|
242
|
-
tracing::error!("MQTT error: {}", e);
|
|
243
|
-
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
244
|
-
}
|
|
245
|
-
_ => {}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
_ = self.shutdown_rx.recv() => {
|
|
249
|
-
tracing::info!("MQTT service shutting down");
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
Ok(())
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async fn on_connect(&self) -> Result<()> {
|
|
258
|
-
// Publish online status (retained)
|
|
259
|
-
self.client
|
|
260
|
-
.publish("system/gateway/status", QoS::AtLeastOnce, true, b"online")
|
|
261
|
-
.await?;
|
|
262
|
-
Ok(())
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
## Reconnection Pattern
|
|
268
|
-
|
|
269
|
-
```rust
|
|
270
|
-
pub async fn run_with_reconnect(config: MqttConfig) {
|
|
271
|
-
loop {
|
|
272
|
-
let mqtt = MqttClient::new(&config);
|
|
273
|
-
let client = mqtt.client();
|
|
274
|
-
let mut event_loop = mqtt.event_loop();
|
|
275
|
-
|
|
276
|
-
if let Err(e) = client.subscribe("sensors/#", QoS::AtLeastOnce).await {
|
|
277
|
-
tracing::error!("Subscribe failed: {}", e);
|
|
278
|
-
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
loop {
|
|
283
|
-
match event_loop.poll().await {
|
|
284
|
-
Ok(event) => handle_event(event).await,
|
|
285
|
-
Err(e) => {
|
|
286
|
-
tracing::error!("Connection error: {}", e);
|
|
287
|
-
break; // Outer loop will reconnect
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
tracing::info!("Reconnecting in 5 seconds...");
|
|
293
|
-
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
## Message Schemas
|
|
299
|
-
|
|
300
|
-
```rust
|
|
301
|
-
use serde::{Deserialize, Serialize};
|
|
302
|
-
use chrono::{DateTime, Utc};
|
|
303
|
-
|
|
304
|
-
#[derive(Debug, Serialize, Deserialize)]
|
|
305
|
-
pub struct SensorReadingMessage {
|
|
306
|
-
pub sensor_id: String,
|
|
307
|
-
pub value: f64,
|
|
308
|
-
pub unit: String,
|
|
309
|
-
pub quality: ReadingQuality,
|
|
310
|
-
pub timestamp: DateTime<Utc>,
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
#[derive(Debug, Serialize, Deserialize)]
|
|
314
|
-
#[serde(rename_all = "snake_case")]
|
|
315
|
-
pub enum ReadingQuality {
|
|
316
|
-
Good,
|
|
317
|
-
Uncertain,
|
|
318
|
-
Bad,
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
#[derive(Debug, Serialize, Deserialize)]
|
|
322
|
-
pub struct AlertMessage {
|
|
323
|
-
pub alert_id: String,
|
|
324
|
-
pub sensor_id: String,
|
|
325
|
-
pub severity: AlertSeverity,
|
|
326
|
-
pub message: String,
|
|
327
|
-
pub triggered_at: DateTime<Utc>,
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
#[derive(Debug, Serialize, Deserialize)]
|
|
331
|
-
#[serde(rename_all = "snake_case")]
|
|
332
|
-
pub enum AlertSeverity {
|
|
333
|
-
Info,
|
|
334
|
-
Warning,
|
|
335
|
-
Critical,
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
## Topic Naming Convention
|
|
340
|
-
|
|
341
|
-
```rust
|
|
342
|
-
pub mod topics {
|
|
343
|
-
// Sensors: sensors/{sensor_id}/{type}
|
|
344
|
-
pub fn sensor_reading(id: &str) -> String { format!("sensors/{}/reading", id) }
|
|
345
|
-
pub fn sensor_status(id: &str) -> String { format!("sensors/{}/status", id) }
|
|
346
|
-
pub fn sensor_config(id: &str) -> String { format!("sensors/{}/config", id) }
|
|
347
|
-
|
|
348
|
-
// Alerts: alerts/{alert_id}/{action}
|
|
349
|
-
pub fn alert_triggered(id: &str) -> String { format!("alerts/{}/triggered", id) }
|
|
350
|
-
pub fn alert_acknowledged(id: &str) -> String { format!("alerts/{}/acknowledged", id) }
|
|
351
|
-
|
|
352
|
-
// System: system/{component}/{type}
|
|
353
|
-
pub const GATEWAY_STATUS: &str = "system/gateway/status";
|
|
354
|
-
pub const GATEWAY_COMMAND: &str = "system/gateway/command";
|
|
355
|
-
|
|
356
|
-
// Wildcards
|
|
357
|
-
pub const ALL_SENSOR_READINGS: &str = "sensors/+/reading";
|
|
358
|
-
pub const ALL_ALERTS: &str = "alerts/#";
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## Anti-Patterns
|
|
363
|
-
|
|
364
|
-
### Retaining Temporal Data
|
|
365
|
-
|
|
366
|
-
```rust
|
|
367
|
-
// ❌ Don't retain frequent readings
|
|
368
|
-
client.publish("sensors/temp/reading", QoS::AtLeastOnce, true, payload);
|
|
369
|
-
|
|
370
|
-
// ✅ Only retain state/status
|
|
371
|
-
client.publish("sensors/temp/status", QoS::AtLeastOnce, true, b"online");
|
|
372
|
-
client.publish("sensors/temp/reading", QoS::AtLeastOnce, false, payload);
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### Using QoS 2 Everywhere
|
|
376
|
-
|
|
377
|
-
```rust
|
|
378
|
-
// ❌ QoS 2 for frequent data - too much overhead
|
|
379
|
-
client.publish("sensors/temp/reading", QoS::ExactlyOnce, false, payload);
|
|
380
|
-
|
|
381
|
-
// ✅ Match QoS to importance
|
|
382
|
-
// Readings: QoS 0 or 1
|
|
383
|
-
// Commands: QoS 1 or 2
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
## Quick Reference
|
|
387
|
-
|
|
388
|
-
| Task | Code |
|
|
389
|
-
|------|------|
|
|
390
|
-
| Publish | `client.publish(topic, QoS::AtLeastOnce, false, payload).await?` |
|
|
391
|
-
| Publish retained | `client.publish(topic, QoS::AtLeastOnce, true, payload).await?` |
|
|
392
|
-
| Subscribe | `client.subscribe(topic, QoS::AtLeastOnce).await?` |
|
|
393
|
-
| Clear retained | `client.publish(topic, QoS::AtLeastOnce, true, b"").await?` |
|
|
394
|
-
| Single wildcard | `sensors/+/reading` |
|
|
395
|
-
| Multi wildcard | `alerts/#` |
|
|
396
|
-
|
|
397
|
-
## Resources
|
|
398
|
-
|
|
399
|
-
- [rumqttc Documentation](https://docs.rs/rumqttc)
|
|
400
|
-
- [MQTT Specification](https://mqtt.org/mqtt-specification/)
|
|
401
|
-
- [HiveMQ MQTT Essentials](https://www.hivemq.com/mqtt-essentials/)
|
|
402
|
-
|
|
403
|
-
## Related Skills
|
|
404
|
-
|
|
405
|
-
- `tokio-async`: Async runtime integration
|
|
406
|
-
- `modbus-protocol`: Industrial data sources
|
|
407
|
-
- `websockets`: Browser data streaming
|
|
408
|
-
- `timescaledb`: Time-series storage
|