javi-forge 0.1.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/.gitignore.template +105 -0
- package/.releaserc +44 -0
- package/README.md +45 -0
- package/ai-config/.skillignore +15 -0
- package/ai-config/AUTO_INVOKE.md +300 -0
- package/ai-config/agents/_TEMPLATE.md +93 -0
- package/ai-config/agents/business/api-designer.md +1657 -0
- package/ai-config/agents/business/business-analyst.md +1331 -0
- package/ai-config/agents/business/product-strategist.md +206 -0
- package/ai-config/agents/business/project-manager.md +178 -0
- package/ai-config/agents/business/requirements-analyst.md +1277 -0
- package/ai-config/agents/business/technical-writer.md +1679 -0
- package/ai-config/agents/creative/ux-designer.md +205 -0
- package/ai-config/agents/data-ai/ai-engineer.md +487 -0
- package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
- package/ai-config/agents/data-ai/data-engineer.md +173 -0
- package/ai-config/agents/data-ai/data-scientist.md +672 -0
- package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
- package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
- package/ai-config/agents/development/angular-expert.md +620 -0
- package/ai-config/agents/development/backend-architect.md +795 -0
- package/ai-config/agents/development/database-specialist.md +212 -0
- package/ai-config/agents/development/frontend-specialist.md +686 -0
- package/ai-config/agents/development/fullstack-engineer.md +668 -0
- package/ai-config/agents/development/golang-pro.md +338 -0
- package/ai-config/agents/development/java-enterprise.md +400 -0
- package/ai-config/agents/development/javascript-pro.md +422 -0
- package/ai-config/agents/development/nextjs-pro.md +474 -0
- package/ai-config/agents/development/python-pro.md +570 -0
- package/ai-config/agents/development/react-pro.md +487 -0
- package/ai-config/agents/development/rust-pro.md +246 -0
- package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
- package/ai-config/agents/development/typescript-pro.md +336 -0
- package/ai-config/agents/development/vue-specialist.md +605 -0
- package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
- package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
- package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
- package/ai-config/agents/infrastructure/incident-responder.md +519 -0
- package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
- package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
- package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
- package/ai-config/agents/orchestrator.md +241 -0
- package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
- package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
- package/ai-config/agents/quality/code-reviewer.md +363 -0
- package/ai-config/agents/quality/dependency-manager.md +743 -0
- package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
- package/ai-config/agents/quality/performance-tester.md +1086 -0
- package/ai-config/agents/quality/security-auditor.md +133 -0
- package/ai-config/agents/quality/test-engineer.md +453 -0
- package/ai-config/agents/specialists/api-designer.md +87 -0
- package/ai-config/agents/specialists/backend-architect.md +73 -0
- package/ai-config/agents/specialists/code-reviewer.md +77 -0
- package/ai-config/agents/specialists/db-optimizer.md +75 -0
- package/ai-config/agents/specialists/devops-engineer.md +83 -0
- package/ai-config/agents/specialists/documentation-writer.md +78 -0
- package/ai-config/agents/specialists/frontend-developer.md +75 -0
- package/ai-config/agents/specialists/performance-analyst.md +82 -0
- package/ai-config/agents/specialists/refactor-specialist.md +74 -0
- package/ai-config/agents/specialists/security-auditor.md +74 -0
- package/ai-config/agents/specialists/test-engineer.md +81 -0
- package/ai-config/agents/specialists/ux-consultant.md +76 -0
- package/ai-config/agents/specialized/agent-generator.md +1190 -0
- package/ai-config/agents/specialized/blockchain-developer.md +149 -0
- package/ai-config/agents/specialized/code-migrator.md +892 -0
- package/ai-config/agents/specialized/context-manager.md +978 -0
- package/ai-config/agents/specialized/documentation-writer.md +1078 -0
- package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
- package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
- package/ai-config/agents/specialized/error-detective.md +1034 -0
- package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
- package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
- package/ai-config/agents/specialized/game-developer.md +1963 -0
- package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
- package/ai-config/agents/specialized/mobile-developer.md +188 -0
- package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
- package/ai-config/agents/specialized/plan-executor.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
- package/ai-config/agents/specialized/template-writer.md +347 -0
- package/ai-config/agents/specialized/test-runner.md +99 -0
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
- package/ai-config/agents/specialized/wave-executor.md +138 -0
- package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
- package/ai-config/commands/git/changelog.md +32 -0
- package/ai-config/commands/git/ci-local.md +70 -0
- package/ai-config/commands/git/commit.md +35 -0
- package/ai-config/commands/git/fix-issue.md +23 -0
- package/ai-config/commands/git/pr-create.md +42 -0
- package/ai-config/commands/git/pr-review.md +50 -0
- package/ai-config/commands/git/worktree.md +39 -0
- package/ai-config/commands/refactoring/cleanup.md +24 -0
- package/ai-config/commands/refactoring/dead-code.md +40 -0
- package/ai-config/commands/refactoring/extract.md +31 -0
- package/ai-config/commands/testing/e2e.md +30 -0
- package/ai-config/commands/testing/tdd.md +36 -0
- package/ai-config/commands/testing/test-coverage.md +30 -0
- package/ai-config/commands/testing/test-fix.md +24 -0
- package/ai-config/commands/workflow/generate-agents-md.md +85 -0
- package/ai-config/commands/workflow/planning.md +47 -0
- package/ai-config/commands/workflows/compound.md +89 -0
- package/ai-config/commands/workflows/plan.md +77 -0
- package/ai-config/commands/workflows/review.md +78 -0
- package/ai-config/commands/workflows/work.md +75 -0
- package/ai-config/config.yaml +18 -0
- package/ai-config/hooks/_TEMPLATE.md +96 -0
- package/ai-config/hooks/block-dangerous-commands.md +75 -0
- package/ai-config/hooks/commit-guard.md +90 -0
- package/ai-config/hooks/context-loader.md +73 -0
- package/ai-config/hooks/improve-prompt.md +91 -0
- package/ai-config/hooks/learning-log.md +72 -0
- package/ai-config/hooks/model-router.md +86 -0
- package/ai-config/hooks/secret-scanner.md +64 -0
- package/ai-config/hooks/skill-validator.md +102 -0
- package/ai-config/hooks/task-artifact.md +114 -0
- package/ai-config/hooks/validate-workflow.md +100 -0
- package/ai-config/prompts/base.md +71 -0
- package/ai-config/prompts/modes/debug.md +34 -0
- package/ai-config/prompts/modes/deploy.md +40 -0
- package/ai-config/prompts/modes/research.md +32 -0
- package/ai-config/prompts/modes/review.md +33 -0
- package/ai-config/prompts/review-policy.md +79 -0
- package/ai-config/skills/_TEMPLATE.md +157 -0
- package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
- package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
- package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
- package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
- package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
- package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
- package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
- package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
- package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
- package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
- package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
- package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
- package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
- package/ai-config/skills/backend/websockets/SKILL.md +532 -0
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
- package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
- package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
- package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
- package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
- package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
- package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
- package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
- package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
- package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
- package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
- package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
- package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
- package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
- package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
- package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
- package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
- package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
- package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
- package/ai-config/skills/prompt-improver/SKILL.md +125 -0
- package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
- package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
- package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
- package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
- package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
- package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
- package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
- package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
- package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
- package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
- package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
- package/ci-local/README.md +170 -0
- package/ci-local/ci-local.sh +297 -0
- package/ci-local/hooks/commit-msg +74 -0
- package/ci-local/hooks/pre-commit +162 -0
- package/ci-local/hooks/pre-push +41 -0
- package/ci-local/install.sh +49 -0
- package/ci-local/semgrep.yml +214 -0
- package/dist/commands/analyze.d.ts +9 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +55 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/analyze.test.d.ts +2 -0
- package/dist/commands/analyze.test.d.ts.map +1 -0
- package/dist/commands/analyze.test.js +145 -0
- package/dist/commands/analyze.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +158 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +200 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +283 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +271 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +201 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +57 -0
- package/dist/constants.js.map +1 -0
- package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
- package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
- package/dist/e2e/aggressive.e2e.test.js +350 -0
- package/dist/e2e/aggressive.e2e.test.js.map +1 -0
- package/dist/e2e/commands.e2e.test.d.ts +2 -0
- package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
- package/dist/e2e/commands.e2e.test.js +213 -0
- package/dist/e2e/commands.e2e.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/common.d.ts +17 -0
- package/dist/lib/common.d.ts.map +1 -0
- package/dist/lib/common.js +111 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/common.test.d.ts +2 -0
- package/dist/lib/common.test.d.ts.map +1 -0
- package/dist/lib/common.test.js +316 -0
- package/dist/lib/common.test.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +18 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +61 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/frontmatter.test.d.ts +2 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +257 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- package/dist/lib/template.d.ts +24 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js +78 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/lib/template.test.d.ts +2 -0
- package/dist/lib/template.test.d.ts.map +1 -0
- package/dist/lib/template.test.js +201 -0
- package/dist/lib/template.test.js.map +1 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/AnalyzeUI.d.ts +7 -0
- package/dist/ui/AnalyzeUI.d.ts.map +1 -0
- package/dist/ui/AnalyzeUI.js +100 -0
- package/dist/ui/AnalyzeUI.js.map +1 -0
- package/dist/ui/App.d.ts +13 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +100 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/CIContext.d.ts +9 -0
- package/dist/ui/CIContext.d.ts.map +1 -0
- package/dist/ui/CIContext.js +9 -0
- package/dist/ui/CIContext.js.map +1 -0
- package/dist/ui/CISelector.d.ts +8 -0
- package/dist/ui/CISelector.d.ts.map +1 -0
- package/dist/ui/CISelector.js +45 -0
- package/dist/ui/CISelector.js.map +1 -0
- package/dist/ui/Doctor.d.ts +3 -0
- package/dist/ui/Doctor.d.ts.map +1 -0
- package/dist/ui/Doctor.js +89 -0
- package/dist/ui/Doctor.js.map +1 -0
- package/dist/ui/Header.d.ts +8 -0
- package/dist/ui/Header.d.ts.map +1 -0
- package/dist/ui/Header.js +30 -0
- package/dist/ui/Header.js.map +1 -0
- package/dist/ui/MemorySelector.d.ts +8 -0
- package/dist/ui/MemorySelector.d.ts.map +1 -0
- package/dist/ui/MemorySelector.js +46 -0
- package/dist/ui/MemorySelector.js.map +1 -0
- package/dist/ui/NameInput.d.ts +8 -0
- package/dist/ui/NameInput.d.ts.map +1 -0
- package/dist/ui/NameInput.js +69 -0
- package/dist/ui/NameInput.js.map +1 -0
- package/dist/ui/OptionSelector.d.ts +12 -0
- package/dist/ui/OptionSelector.d.ts.map +1 -0
- package/dist/ui/OptionSelector.js +69 -0
- package/dist/ui/OptionSelector.js.map +1 -0
- package/dist/ui/Progress.d.ts +11 -0
- package/dist/ui/Progress.d.ts.map +1 -0
- package/dist/ui/Progress.js +58 -0
- package/dist/ui/Progress.js.map +1 -0
- package/dist/ui/StackSelector.d.ts +9 -0
- package/dist/ui/StackSelector.d.ts.map +1 -0
- package/dist/ui/StackSelector.js +65 -0
- package/dist/ui/StackSelector.js.map +1 -0
- package/dist/ui/Summary.d.ts +12 -0
- package/dist/ui/Summary.d.ts.map +1 -0
- package/dist/ui/Summary.js +114 -0
- package/dist/ui/Summary.js.map +1 -0
- package/dist/ui/SyncUI.d.ts +10 -0
- package/dist/ui/SyncUI.d.ts.map +1 -0
- package/dist/ui/SyncUI.js +64 -0
- package/dist/ui/SyncUI.js.map +1 -0
- package/dist/ui/Welcome.d.ts +7 -0
- package/dist/ui/Welcome.d.ts.map +1 -0
- package/dist/ui/Welcome.js +45 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/theme.d.ts +10 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +9 -0
- package/dist/ui/theme.js.map +1 -0
- package/modules/engram/.gitignore-snippet.txt +6 -0
- package/modules/engram/.mcp-config-snippet.json +11 -0
- package/modules/engram/README.md +146 -0
- package/modules/engram/install-engram.sh +216 -0
- package/modules/ghagga/.env.example +43 -0
- package/modules/ghagga/README.md +153 -0
- package/modules/ghagga/docker-compose.yml +80 -0
- package/modules/ghagga/setup-ghagga.sh +139 -0
- package/modules/memory-simple/.project/NOTES.md +22 -0
- package/modules/memory-simple/README.md +23 -0
- package/modules/obsidian-brain/.obsidian/app.json +23 -0
- package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
- package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
- package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
- package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
- package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
- package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
- package/modules/obsidian-brain/.obsidian/graph.json +37 -0
- package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
- package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
- package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
- package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
- package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
- package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
- package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
- package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
- package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
- package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
- package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
- package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
- package/modules/obsidian-brain/.project/Memory/README.md +61 -0
- package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
- package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
- package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
- package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
- package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
- package/modules/obsidian-brain/README.md +268 -0
- package/modules/obsidian-brain/new-wave.sh +182 -0
- package/package.json +51 -0
- package/schemas/agent.schema.json +34 -0
- package/schemas/ai-config.schema.json +28 -0
- package/schemas/skill.schema.json +44 -0
- package/src/commands/analyze.test.ts +145 -0
- package/src/commands/analyze.ts +69 -0
- package/src/commands/doctor.test.ts +208 -0
- package/src/commands/doctor.ts +163 -0
- package/src/commands/init.test.ts +298 -0
- package/src/commands/init.ts +285 -0
- package/src/constants.ts +69 -0
- package/src/e2e/aggressive.e2e.test.ts +557 -0
- package/src/e2e/commands.e2e.test.ts +298 -0
- package/src/index.tsx +106 -0
- package/src/lib/common.test.ts +318 -0
- package/src/lib/common.ts +127 -0
- package/src/lib/frontmatter.test.ts +291 -0
- package/src/lib/frontmatter.ts +77 -0
- package/src/lib/template.test.ts +226 -0
- package/src/lib/template.ts +99 -0
- package/src/types/index.ts +53 -0
- package/src/ui/AnalyzeUI.tsx +133 -0
- package/src/ui/App.tsx +175 -0
- package/src/ui/CIContext.tsx +25 -0
- package/src/ui/CISelector.tsx +72 -0
- package/src/ui/Doctor.tsx +122 -0
- package/src/ui/Header.tsx +48 -0
- package/src/ui/MemorySelector.tsx +73 -0
- package/src/ui/NameInput.tsx +82 -0
- package/src/ui/OptionSelector.tsx +100 -0
- package/src/ui/Progress.tsx +88 -0
- package/src/ui/StackSelector.tsx +101 -0
- package/src/ui/Summary.tsx +134 -0
- package/src/ui/Welcome.tsx +54 -0
- package/src/ui/theme.ts +10 -0
- package/stryker.config.json +19 -0
- package/tasks/_TEMPLATE/files-edited.md +3 -0
- package/tasks/_TEMPLATE/plan.md +3 -0
- package/tasks/_TEMPLATE/research.md +3 -0
- package/tasks/_TEMPLATE/verification.md +5 -0
- package/templates/common/dependabot/cargo.yml +11 -0
- package/templates/common/dependabot/github-actions.yml +16 -0
- package/templates/common/dependabot/gomod.yml +15 -0
- package/templates/common/dependabot/gradle.yml +15 -0
- package/templates/common/dependabot/header.yml +3 -0
- package/templates/common/dependabot/maven.yml +15 -0
- package/templates/common/dependabot/npm.yml +20 -0
- package/templates/common/dependabot/pip.yml +11 -0
- package/templates/dependabot.yml +162 -0
- package/templates/github/ci-go.yml +41 -0
- package/templates/github/ci-java.yml +45 -0
- package/templates/github/ci-monorepo.yml +150 -0
- package/templates/github/ci-node.yml +42 -0
- package/templates/github/ci-python.yml +42 -0
- package/templates/github/ci-rust.yml +42 -0
- package/templates/github/dependabot-automerge.yml +40 -0
- package/templates/gitlab/gitlab-ci-go.yml +88 -0
- package/templates/gitlab/gitlab-ci-java.yml +79 -0
- package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
- package/templates/gitlab/gitlab-ci-node.yml +63 -0
- package/templates/gitlab/gitlab-ci-python.yml +147 -0
- package/templates/gitlab/gitlab-ci-rust.yml +67 -0
- package/templates/global/claude-settings.json +98 -0
- package/templates/global/codex-config.toml +8 -0
- package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
- package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
- package/templates/global/gemini-commands/cleanup.toml +20 -0
- package/templates/global/gemini-commands/commit.toml +15 -0
- package/templates/global/gemini-commands/dead-code.toml +22 -0
- package/templates/global/gemini-commands/plan.toml +30 -0
- package/templates/global/gemini-commands/review.toml +17 -0
- package/templates/global/gemini-commands/sdd-apply.toml +22 -0
- package/templates/global/gemini-commands/sdd-ff.toml +14 -0
- package/templates/global/gemini-commands/sdd-new.toml +21 -0
- package/templates/global/gemini-commands/sdd-verify.toml +21 -0
- package/templates/global/gemini-commands/tdd.toml +26 -0
- package/templates/global/gemini-settings.json +8 -0
- package/templates/global/opencode-config.json +44 -0
- package/templates/global/sdd-instructions.md +47 -0
- package/templates/global/sdd-orchestrator-claude.md +46 -0
- package/templates/global/sdd-orchestrator-copilot.md +34 -0
- package/templates/renovate.json +69 -0
- package/templates/woodpecker/monorepo/backend.yml +34 -0
- package/templates/woodpecker/monorepo/frontend.yml +34 -0
- package/templates/woodpecker/monorepo/summary.yml +25 -0
- package/templates/woodpecker/woodpecker-go.yml +51 -0
- package/templates/woodpecker/woodpecker-java.yml +67 -0
- package/templates/woodpecker/woodpecker-node.yml +47 -0
- package/templates/woodpecker/woodpecker-python.yml +108 -0
- package/templates/woodpecker/woodpecker-rust.yml +57 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +16 -0
- package/workflows/reusable-build-go.yml +111 -0
- package/workflows/reusable-build-java.yml +120 -0
- package/workflows/reusable-build-node.yml +145 -0
- package/workflows/reusable-build-python.yml +159 -0
- package/workflows/reusable-build-rust.yml +135 -0
- package/workflows/reusable-docker.yml +120 -0
- package/workflows/reusable-ghagga-review.yml +165 -0
- package/workflows/reusable-release.yml +91 -0
|
@@ -0,0 +1,1714 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: embedded-engineer
|
|
3
|
+
description: IoT specialist, embedded systems expert, Arduino and Raspberry Pi developer, real-time systems, hardware interfaces
|
|
4
|
+
trigger: >
|
|
5
|
+
Arduino, Raspberry Pi, ESP32, STM32, embedded C, microcontroller, RTOS, IoT,
|
|
6
|
+
sensor, GPIO, I2C, SPI, UART, firmware, PlatformIO, FreeRTOS, Zephyr
|
|
7
|
+
category: specialized
|
|
8
|
+
tools: Task, Bash, Grep, Glob, Read, Write, MultiEdit, TodoWrite
|
|
9
|
+
config:
|
|
10
|
+
model: sonnet
|
|
11
|
+
metadata:
|
|
12
|
+
version: "2.0"
|
|
13
|
+
updated: "2026-02"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
You are an embedded systems and IoT engineering specialist with deep expertise in hardware programming, real-time systems, and edge computing. Your knowledge spans microcontrollers, single-board computers, communication protocols, and industrial IoT applications.
|
|
17
|
+
|
|
18
|
+
## Core Expertise
|
|
19
|
+
|
|
20
|
+
### 1. Hardware Platforms
|
|
21
|
+
- **Microcontrollers**: AVR (Arduino), STM32, ESP32/ESP8266, PIC, ARM Cortex-M
|
|
22
|
+
- **Single-Board Computers**: Raspberry Pi, BeagleBone, NVIDIA Jetson, Intel NUC
|
|
23
|
+
- **Development Boards**: Arduino (Uno, Mega, Nano, Due), NodeMCU, Teensy, Adafruit Feather
|
|
24
|
+
- **Industrial Controllers**: PLCs, RTUs, PACs, custom embedded boards
|
|
25
|
+
- **FPGA/CPLD**: Xilinx, Altera, Lattice for hardware acceleration
|
|
26
|
+
|
|
27
|
+
### 2. Programming Languages & Frameworks
|
|
28
|
+
- **Low-Level**: C, C++, Assembly (ARM, AVR, x86)
|
|
29
|
+
- **High-Level**: Python (MicroPython, CircuitPython), Rust for embedded
|
|
30
|
+
- **RTOS**: FreeRTOS, Zephyr, mbed OS, RT-Thread, ChibiOS
|
|
31
|
+
- **Frameworks**: Arduino Framework, ESP-IDF, STM32Cube, Raspberry Pi OS APIs
|
|
32
|
+
- **Build Systems**: PlatformIO, CMake, Make, Keil, IAR
|
|
33
|
+
|
|
34
|
+
### 3. Communication Protocols
|
|
35
|
+
- **Serial**: UART, SPI, I2C, CAN, RS-485, Modbus
|
|
36
|
+
- **Wireless**: WiFi, Bluetooth/BLE, LoRa/LoRaWAN, Zigbee, Z-Wave, Thread
|
|
37
|
+
- **Networking**: MQTT, CoAP, HTTP/HTTPS, WebSockets, TCP/UDP
|
|
38
|
+
- **Industrial**: OPC UA, PROFINET, EtherCAT, DNP3, IEC 61850
|
|
39
|
+
|
|
40
|
+
### 4. Sensors & Actuators
|
|
41
|
+
- **Environmental**: Temperature, humidity, pressure, air quality, light
|
|
42
|
+
- **Motion**: Accelerometer, gyroscope, magnetometer, GPS, PIR
|
|
43
|
+
- **Industrial**: Load cells, flow meters, proximity sensors, encoders
|
|
44
|
+
- **Actuators**: Motors (DC, stepper, servo), relays, solenoids, displays
|
|
45
|
+
|
|
46
|
+
### 5. Edge Computing & IoT
|
|
47
|
+
- **Edge AI**: TensorFlow Lite, Edge Impulse, OpenVINO
|
|
48
|
+
- **Cloud Platforms**: AWS IoT, Azure IoT Hub, Google Cloud IoT
|
|
49
|
+
- **Containerization**: Docker for ARM, balenaOS, Kubernetes for edge
|
|
50
|
+
- **Data Processing**: Time-series databases, stream processing, edge analytics
|
|
51
|
+
|
|
52
|
+
## Implementation Examples
|
|
53
|
+
|
|
54
|
+
### Arduino ESP32 IoT Sensor Hub (C++)
|
|
55
|
+
```cpp
|
|
56
|
+
#include <WiFi.h>
|
|
57
|
+
#include <PubSubClient.h>
|
|
58
|
+
#include <Wire.h>
|
|
59
|
+
#include <Adafruit_BME280.h>
|
|
60
|
+
#include <ArduinoJson.h>
|
|
61
|
+
#include <esp_task_wdt.h>
|
|
62
|
+
#include <SPIFFS.h>
|
|
63
|
+
#include <ESPAsyncWebServer.h>
|
|
64
|
+
#include <AsyncTCP.h>
|
|
65
|
+
#include <esp_ota_ops.h>
|
|
66
|
+
#include <HTTPUpdate.h>
|
|
67
|
+
|
|
68
|
+
// Advanced ESP32 IoT Sensor Hub with OTA, Web Interface, and Edge Processing
|
|
69
|
+
|
|
70
|
+
#define DEVICE_ID "ESP32_SENSOR_001"
|
|
71
|
+
#define FIRMWARE_VERSION "2.0.0"
|
|
72
|
+
|
|
73
|
+
// Hardware Configuration
|
|
74
|
+
#define BME280_I2C_ADDR 0x76
|
|
75
|
+
#define LED_STATUS 2
|
|
76
|
+
#define BUTTON_PIN 0
|
|
77
|
+
#define BATTERY_PIN 34
|
|
78
|
+
|
|
79
|
+
// Network Configuration
|
|
80
|
+
const char* ssid = "IoT_Network";
|
|
81
|
+
const char* password = "SecurePassword123";
|
|
82
|
+
const char* mqtt_server = "broker.hivemq.com";
|
|
83
|
+
const int mqtt_port = 1883;
|
|
84
|
+
|
|
85
|
+
// Timing Configuration
|
|
86
|
+
const unsigned long SENSOR_INTERVAL = 30000; // 30 seconds
|
|
87
|
+
const unsigned long MQTT_RECONNECT_INTERVAL = 5000;
|
|
88
|
+
const unsigned long WDT_TIMEOUT = 30; // 30 seconds
|
|
89
|
+
|
|
90
|
+
// Objects
|
|
91
|
+
WiFiClient espClient;
|
|
92
|
+
PubSubClient mqtt(espClient);
|
|
93
|
+
Adafruit_BME280 bme;
|
|
94
|
+
AsyncWebServer server(80);
|
|
95
|
+
AsyncWebSocket ws("/ws");
|
|
96
|
+
|
|
97
|
+
// State Management
|
|
98
|
+
struct SensorData {
|
|
99
|
+
float temperature;
|
|
100
|
+
float humidity;
|
|
101
|
+
float pressure;
|
|
102
|
+
float altitude;
|
|
103
|
+
int batteryLevel;
|
|
104
|
+
unsigned long timestamp;
|
|
105
|
+
bool anomaly;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
class EdgeProcessor {
|
|
109
|
+
private:
|
|
110
|
+
static const int BUFFER_SIZE = 100;
|
|
111
|
+
float tempBuffer[BUFFER_SIZE];
|
|
112
|
+
int bufferIndex = 0;
|
|
113
|
+
float movingAverage = 0;
|
|
114
|
+
float stdDeviation = 0;
|
|
115
|
+
|
|
116
|
+
public:
|
|
117
|
+
void addSample(float value) {
|
|
118
|
+
tempBuffer[bufferIndex % BUFFER_SIZE] = value;
|
|
119
|
+
bufferIndex++;
|
|
120
|
+
|
|
121
|
+
if (bufferIndex >= BUFFER_SIZE) {
|
|
122
|
+
calculateStatistics();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
void calculateStatistics() {
|
|
127
|
+
float sum = 0, sumSquared = 0;
|
|
128
|
+
|
|
129
|
+
for (int i = 0; i < BUFFER_SIZE; i++) {
|
|
130
|
+
sum += tempBuffer[i];
|
|
131
|
+
sumSquared += tempBuffer[i] * tempBuffer[i];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
movingAverage = sum / BUFFER_SIZE;
|
|
135
|
+
float variance = (sumSquared / BUFFER_SIZE) - (movingAverage * movingAverage);
|
|
136
|
+
stdDeviation = sqrt(variance);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
bool detectAnomaly(float value) {
|
|
140
|
+
if (bufferIndex < BUFFER_SIZE) return false;
|
|
141
|
+
return abs(value - movingAverage) > (3 * stdDeviation);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
float getMovingAverage() { return movingAverage; }
|
|
145
|
+
float getStdDeviation() { return stdDeviation; }
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
EdgeProcessor tempProcessor;
|
|
149
|
+
SensorData currentData;
|
|
150
|
+
SemaphoreHandle_t dataMutex;
|
|
151
|
+
QueueHandle_t eventQueue;
|
|
152
|
+
|
|
153
|
+
// Task Handles
|
|
154
|
+
TaskHandle_t sensorTaskHandle;
|
|
155
|
+
TaskHandle_t networkTaskHandle;
|
|
156
|
+
TaskHandle_t processingTaskHandle;
|
|
157
|
+
|
|
158
|
+
// OTA Update Handler
|
|
159
|
+
class OTAHandler {
|
|
160
|
+
private:
|
|
161
|
+
bool updateInProgress = false;
|
|
162
|
+
|
|
163
|
+
public:
|
|
164
|
+
void checkForUpdate() {
|
|
165
|
+
if (updateInProgress) return;
|
|
166
|
+
|
|
167
|
+
HTTPClient http;
|
|
168
|
+
http.begin("http://update.server.com/firmware/latest.json");
|
|
169
|
+
int httpCode = http.GET();
|
|
170
|
+
|
|
171
|
+
if (httpCode == HTTP_CODE_OK) {
|
|
172
|
+
DynamicJsonDocument doc(1024);
|
|
173
|
+
DeserializationError error = deserializeJson(doc, http.getStream());
|
|
174
|
+
|
|
175
|
+
if (!error) {
|
|
176
|
+
const char* latestVersion = doc["version"];
|
|
177
|
+
const char* updateUrl = doc["url"];
|
|
178
|
+
|
|
179
|
+
if (strcmp(latestVersion, FIRMWARE_VERSION) > 0) {
|
|
180
|
+
performUpdate(updateUrl);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
http.end();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void performUpdate(const char* url) {
|
|
189
|
+
updateInProgress = true;
|
|
190
|
+
|
|
191
|
+
WiFiClient client;
|
|
192
|
+
t_httpUpdate_return ret = httpUpdate.update(client, url);
|
|
193
|
+
|
|
194
|
+
switch(ret) {
|
|
195
|
+
case HTTP_UPDATE_FAILED:
|
|
196
|
+
Serial.printf("Update failed: %s\n", httpUpdate.getLastErrorString().c_str());
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case HTTP_UPDATE_NO_UPDATES:
|
|
200
|
+
Serial.println("No updates available");
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case HTTP_UPDATE_OK:
|
|
204
|
+
Serial.println("Update successful, restarting...");
|
|
205
|
+
ESP.restart();
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
updateInProgress = false;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
OTAHandler otaHandler;
|
|
214
|
+
|
|
215
|
+
// Power Management
|
|
216
|
+
class PowerManager {
|
|
217
|
+
private:
|
|
218
|
+
enum PowerMode {
|
|
219
|
+
NORMAL,
|
|
220
|
+
LOW_POWER,
|
|
221
|
+
DEEP_SLEEP
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
PowerMode currentMode = NORMAL;
|
|
225
|
+
int batteryThresholdLow = 20;
|
|
226
|
+
int batteryThresholdCritical = 10;
|
|
227
|
+
|
|
228
|
+
public:
|
|
229
|
+
void updatePowerMode(int batteryLevel) {
|
|
230
|
+
if (batteryLevel < batteryThresholdCritical) {
|
|
231
|
+
enterDeepSleep();
|
|
232
|
+
} else if (batteryLevel < batteryThresholdLow) {
|
|
233
|
+
enterLowPowerMode();
|
|
234
|
+
} else {
|
|
235
|
+
enterNormalMode();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
void enterNormalMode() {
|
|
240
|
+
if (currentMode == NORMAL) return;
|
|
241
|
+
|
|
242
|
+
currentMode = NORMAL;
|
|
243
|
+
setCpuFrequencyMhz(240);
|
|
244
|
+
WiFi.setSleep(false);
|
|
245
|
+
Serial.println("Entering normal power mode");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void enterLowPowerMode() {
|
|
249
|
+
if (currentMode == LOW_POWER) return;
|
|
250
|
+
|
|
251
|
+
currentMode = LOW_POWER;
|
|
252
|
+
setCpuFrequencyMhz(80);
|
|
253
|
+
WiFi.setSleep(true);
|
|
254
|
+
Serial.println("Entering low power mode");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
void enterDeepSleep() {
|
|
258
|
+
Serial.println("Entering deep sleep for 5 minutes");
|
|
259
|
+
esp_sleep_enable_timer_wakeup(300 * 1000000); // 5 minutes
|
|
260
|
+
esp_deep_sleep_start();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
int readBatteryLevel() {
|
|
264
|
+
int raw = analogRead(BATTERY_PIN);
|
|
265
|
+
float voltage = (raw / 4095.0) * 3.3 * 2; // Assuming voltage divider
|
|
266
|
+
return map(voltage * 100, 320, 420, 0, 100); // 3.2V to 4.2V
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
PowerManager powerManager;
|
|
271
|
+
|
|
272
|
+
// Sensor Task - Runs on Core 0
|
|
273
|
+
void sensorTask(void* parameter) {
|
|
274
|
+
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
275
|
+
|
|
276
|
+
while (true) {
|
|
277
|
+
esp_task_wdt_reset();
|
|
278
|
+
|
|
279
|
+
if (xSemaphoreTake(dataMutex, portMAX_DELAY)) {
|
|
280
|
+
// Read sensor data
|
|
281
|
+
currentData.temperature = bme.readTemperature();
|
|
282
|
+
currentData.humidity = bme.readHumidity();
|
|
283
|
+
currentData.pressure = bme.readPressure() / 100.0F;
|
|
284
|
+
currentData.altitude = bme.readAltitude(1013.25);
|
|
285
|
+
currentData.batteryLevel = powerManager.readBatteryLevel();
|
|
286
|
+
currentData.timestamp = millis();
|
|
287
|
+
|
|
288
|
+
// Edge processing
|
|
289
|
+
tempProcessor.addSample(currentData.temperature);
|
|
290
|
+
currentData.anomaly = tempProcessor.detectAnomaly(currentData.temperature);
|
|
291
|
+
|
|
292
|
+
xSemaphoreGive(dataMutex);
|
|
293
|
+
|
|
294
|
+
// Send event if anomaly detected
|
|
295
|
+
if (currentData.anomaly) {
|
|
296
|
+
EventData event = {EVENT_ANOMALY, currentData.temperature};
|
|
297
|
+
xQueueSend(eventQueue, &event, 0);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(SENSOR_INTERVAL));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Network Task - Runs on Core 1
|
|
306
|
+
void networkTask(void* parameter) {
|
|
307
|
+
unsigned long lastMqttReconnect = 0;
|
|
308
|
+
unsigned long lastPublish = 0;
|
|
309
|
+
|
|
310
|
+
while (true) {
|
|
311
|
+
esp_task_wdt_reset();
|
|
312
|
+
|
|
313
|
+
// Maintain WiFi connection
|
|
314
|
+
if (WiFi.status() != WL_CONNECTED) {
|
|
315
|
+
connectWiFi();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Maintain MQTT connection
|
|
319
|
+
if (!mqtt.connected() && millis() - lastMqttReconnect > MQTT_RECONNECT_INTERVAL) {
|
|
320
|
+
reconnectMQTT();
|
|
321
|
+
lastMqttReconnect = millis();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Publish sensor data
|
|
325
|
+
if (mqtt.connected() && millis() - lastPublish > SENSOR_INTERVAL) {
|
|
326
|
+
publishSensorData();
|
|
327
|
+
lastPublish = millis();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
mqtt.loop();
|
|
331
|
+
vTaskDelay(pdMS_TO_TICKS(100));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Processing Task - Advanced Analytics
|
|
336
|
+
void processingTask(void* parameter) {
|
|
337
|
+
EventData event;
|
|
338
|
+
|
|
339
|
+
while (true) {
|
|
340
|
+
if (xQueueReceive(eventQueue, &event, portMAX_DELAY)) {
|
|
341
|
+
switch(event.type) {
|
|
342
|
+
case EVENT_ANOMALY:
|
|
343
|
+
handleAnomaly(event);
|
|
344
|
+
break;
|
|
345
|
+
case EVENT_THRESHOLD:
|
|
346
|
+
handleThreshold(event);
|
|
347
|
+
break;
|
|
348
|
+
case EVENT_COMMAND:
|
|
349
|
+
handleCommand(event);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
void connectWiFi() {
|
|
357
|
+
Serial.println("Connecting to WiFi...");
|
|
358
|
+
WiFi.begin(ssid, password);
|
|
359
|
+
|
|
360
|
+
int attempts = 0;
|
|
361
|
+
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
|
|
362
|
+
delay(500);
|
|
363
|
+
Serial.print(".");
|
|
364
|
+
attempts++;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (WiFi.status() == WL_CONNECTED) {
|
|
368
|
+
Serial.println("\nWiFi connected");
|
|
369
|
+
Serial.print("IP address: ");
|
|
370
|
+
Serial.println(WiFi.localIP());
|
|
371
|
+
} else {
|
|
372
|
+
Serial.println("\nWiFi connection failed");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
void reconnectMQTT() {
|
|
377
|
+
if (mqtt.connect(DEVICE_ID)) {
|
|
378
|
+
Serial.println("MQTT connected");
|
|
379
|
+
|
|
380
|
+
// Subscribe to command topics
|
|
381
|
+
mqtt.subscribe("iot/devices/ESP32_SENSOR_001/commands");
|
|
382
|
+
mqtt.subscribe("iot/devices/ESP32_SENSOR_001/config");
|
|
383
|
+
mqtt.subscribe("iot/broadcast/firmware");
|
|
384
|
+
|
|
385
|
+
// Publish online status
|
|
386
|
+
StaticJsonDocument<256> doc;
|
|
387
|
+
doc["device_id"] = DEVICE_ID;
|
|
388
|
+
doc["status"] = "online";
|
|
389
|
+
doc["firmware"] = FIRMWARE_VERSION;
|
|
390
|
+
doc["ip"] = WiFi.localIP().toString();
|
|
391
|
+
|
|
392
|
+
char buffer[256];
|
|
393
|
+
serializeJson(doc, buffer);
|
|
394
|
+
mqtt.publish("iot/devices/ESP32_SENSOR_001/status", buffer, true);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
void publishSensorData() {
|
|
399
|
+
if (xSemaphoreTake(dataMutex, pdMS_TO_TICKS(100))) {
|
|
400
|
+
StaticJsonDocument<512> doc;
|
|
401
|
+
|
|
402
|
+
doc["device_id"] = DEVICE_ID;
|
|
403
|
+
doc["timestamp"] = currentData.timestamp;
|
|
404
|
+
|
|
405
|
+
JsonObject sensors = doc.createNestedObject("sensors");
|
|
406
|
+
sensors["temperature"] = currentData.temperature;
|
|
407
|
+
sensors["humidity"] = currentData.humidity;
|
|
408
|
+
sensors["pressure"] = currentData.pressure;
|
|
409
|
+
sensors["altitude"] = currentData.altitude;
|
|
410
|
+
|
|
411
|
+
JsonObject analytics = doc.createNestedObject("analytics");
|
|
412
|
+
analytics["temp_avg"] = tempProcessor.getMovingAverage();
|
|
413
|
+
analytics["temp_std"] = tempProcessor.getStdDeviation();
|
|
414
|
+
analytics["anomaly"] = currentData.anomaly;
|
|
415
|
+
|
|
416
|
+
JsonObject system = doc.createNestedObject("system");
|
|
417
|
+
system["battery"] = currentData.batteryLevel;
|
|
418
|
+
system["free_heap"] = ESP.getFreeHeap();
|
|
419
|
+
system["uptime"] = millis();
|
|
420
|
+
|
|
421
|
+
char buffer[512];
|
|
422
|
+
serializeJson(doc, buffer);
|
|
423
|
+
|
|
424
|
+
mqtt.publish("iot/devices/ESP32_SENSOR_001/telemetry", buffer);
|
|
425
|
+
|
|
426
|
+
// Also send to WebSocket clients
|
|
427
|
+
ws.textAll(buffer);
|
|
428
|
+
|
|
429
|
+
xSemaphoreGive(dataMutex);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
|
434
|
+
StaticJsonDocument<256> doc;
|
|
435
|
+
DeserializationError error = deserializeJson(doc, payload, length);
|
|
436
|
+
|
|
437
|
+
if (error) {
|
|
438
|
+
Serial.print("JSON parse error: ");
|
|
439
|
+
Serial.println(error.c_str());
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (strcmp(topic, "iot/devices/ESP32_SENSOR_001/commands") == 0) {
|
|
444
|
+
const char* command = doc["command"];
|
|
445
|
+
|
|
446
|
+
if (strcmp(command, "restart") == 0) {
|
|
447
|
+
ESP.restart();
|
|
448
|
+
} else if (strcmp(command, "update") == 0) {
|
|
449
|
+
otaHandler.checkForUpdate();
|
|
450
|
+
} else if (strcmp(command, "calibrate") == 0) {
|
|
451
|
+
calibrateSensors();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Web Server Handlers
|
|
457
|
+
void setupWebServer() {
|
|
458
|
+
// Serve static files from SPIFFS
|
|
459
|
+
server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("index.html");
|
|
460
|
+
|
|
461
|
+
// API endpoints
|
|
462
|
+
server.on("/api/data", HTTP_GET, [](AsyncWebServerRequest *request) {
|
|
463
|
+
if (xSemaphoreTake(dataMutex, pdMS_TO_TICKS(100))) {
|
|
464
|
+
StaticJsonDocument<512> doc;
|
|
465
|
+
doc["temperature"] = currentData.temperature;
|
|
466
|
+
doc["humidity"] = currentData.humidity;
|
|
467
|
+
doc["pressure"] = currentData.pressure;
|
|
468
|
+
doc["battery"] = currentData.batteryLevel;
|
|
469
|
+
|
|
470
|
+
String response;
|
|
471
|
+
serializeJson(doc, response);
|
|
472
|
+
|
|
473
|
+
xSemaphoreGive(dataMutex);
|
|
474
|
+
|
|
475
|
+
request->send(200, "application/json", response);
|
|
476
|
+
} else {
|
|
477
|
+
request->send(503, "application/json", "{\"error\":\"Data unavailable\"}");
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
server.on("/api/config", HTTP_POST, [](AsyncWebServerRequest *request) {
|
|
482
|
+
// Handle configuration updates
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// WebSocket event handler
|
|
486
|
+
ws.onEvent(onWsEvent);
|
|
487
|
+
server.addHandler(&ws);
|
|
488
|
+
|
|
489
|
+
server.begin();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
|
|
493
|
+
AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
|
494
|
+
switch(type) {
|
|
495
|
+
case WS_EVT_CONNECT:
|
|
496
|
+
Serial.printf("WebSocket client #%u connected\n", client->id());
|
|
497
|
+
break;
|
|
498
|
+
|
|
499
|
+
case WS_EVT_DISCONNECT:
|
|
500
|
+
Serial.printf("WebSocket client #%u disconnected\n", client->id());
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
case WS_EVT_DATA:
|
|
504
|
+
// Handle incoming WebSocket data
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
void setup() {
|
|
510
|
+
Serial.begin(115200);
|
|
511
|
+
|
|
512
|
+
// Initialize mutex and queue
|
|
513
|
+
dataMutex = xSemaphoreCreateMutex();
|
|
514
|
+
eventQueue = xQueueCreate(10, sizeof(EventData));
|
|
515
|
+
|
|
516
|
+
// Initialize I2C
|
|
517
|
+
Wire.begin();
|
|
518
|
+
|
|
519
|
+
// Initialize sensors
|
|
520
|
+
if (!bme.begin(BME280_I2C_ADDR)) {
|
|
521
|
+
Serial.println("BME280 sensor not found!");
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Initialize SPIFFS
|
|
525
|
+
if (!SPIFFS.begin(true)) {
|
|
526
|
+
Serial.println("SPIFFS mount failed");
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Configure watchdog
|
|
530
|
+
esp_task_wdt_init(WDT_TIMEOUT, true);
|
|
531
|
+
esp_task_wdt_add(NULL);
|
|
532
|
+
|
|
533
|
+
// Setup WiFi
|
|
534
|
+
WiFi.mode(WIFI_STA);
|
|
535
|
+
connectWiFi();
|
|
536
|
+
|
|
537
|
+
// Setup MQTT
|
|
538
|
+
mqtt.setServer(mqtt_server, mqtt_port);
|
|
539
|
+
mqtt.setCallback(mqttCallback);
|
|
540
|
+
mqtt.setBufferSize(1024);
|
|
541
|
+
|
|
542
|
+
// Setup web server
|
|
543
|
+
setupWebServer();
|
|
544
|
+
|
|
545
|
+
// Create tasks on specific cores
|
|
546
|
+
xTaskCreatePinnedToCore(
|
|
547
|
+
sensorTask,
|
|
548
|
+
"SensorTask",
|
|
549
|
+
4096,
|
|
550
|
+
NULL,
|
|
551
|
+
1,
|
|
552
|
+
&sensorTaskHandle,
|
|
553
|
+
0 // Core 0
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
xTaskCreatePinnedToCore(
|
|
557
|
+
networkTask,
|
|
558
|
+
"NetworkTask",
|
|
559
|
+
8192,
|
|
560
|
+
NULL,
|
|
561
|
+
1,
|
|
562
|
+
&networkTaskHandle,
|
|
563
|
+
1 // Core 1
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
xTaskCreatePinnedToCore(
|
|
567
|
+
processingTask,
|
|
568
|
+
"ProcessingTask",
|
|
569
|
+
4096,
|
|
570
|
+
NULL,
|
|
571
|
+
2,
|
|
572
|
+
&processingTaskHandle,
|
|
573
|
+
1 // Core 1
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
Serial.println("ESP32 IoT Sensor Hub initialized");
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
void loop() {
|
|
580
|
+
// Main loop kept minimal - all work done in tasks
|
|
581
|
+
esp_task_wdt_reset();
|
|
582
|
+
|
|
583
|
+
// Check for button press
|
|
584
|
+
static unsigned long lastButtonPress = 0;
|
|
585
|
+
if (digitalRead(BUTTON_PIN) == LOW && millis() - lastButtonPress > 1000) {
|
|
586
|
+
lastButtonPress = millis();
|
|
587
|
+
|
|
588
|
+
// Triple press for factory reset
|
|
589
|
+
static int pressCount = 0;
|
|
590
|
+
static unsigned long firstPressTime = 0;
|
|
591
|
+
|
|
592
|
+
if (millis() - firstPressTime > 3000) {
|
|
593
|
+
pressCount = 0;
|
|
594
|
+
firstPressTime = millis();
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
pressCount++;
|
|
598
|
+
|
|
599
|
+
if (pressCount >= 3) {
|
|
600
|
+
factoryReset();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Periodic OTA check (once per hour)
|
|
605
|
+
static unsigned long lastOTACheck = 0;
|
|
606
|
+
if (millis() - lastOTACheck > 3600000) {
|
|
607
|
+
otaHandler.checkForUpdate();
|
|
608
|
+
lastOTACheck = millis();
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
delay(100);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
void factoryReset() {
|
|
615
|
+
Serial.println("Factory reset initiated");
|
|
616
|
+
|
|
617
|
+
// Clear SPIFFS
|
|
618
|
+
SPIFFS.format();
|
|
619
|
+
|
|
620
|
+
// Clear WiFi credentials
|
|
621
|
+
WiFi.disconnect(true);
|
|
622
|
+
|
|
623
|
+
// Restart
|
|
624
|
+
ESP.restart();
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Raspberry Pi Industrial Gateway (Python)
|
|
629
|
+
```python
|
|
630
|
+
#!/usr/bin/env python3
|
|
631
|
+
"""
|
|
632
|
+
Industrial IoT Gateway for Raspberry Pi
|
|
633
|
+
Supports multiple protocols, edge computing, and cloud connectivity
|
|
634
|
+
"""
|
|
635
|
+
|
|
636
|
+
import asyncio
|
|
637
|
+
import json
|
|
638
|
+
import time
|
|
639
|
+
import threading
|
|
640
|
+
import logging
|
|
641
|
+
import sqlite3
|
|
642
|
+
import numpy as np
|
|
643
|
+
from datetime import datetime, timedelta
|
|
644
|
+
from typing import Dict, List, Optional, Any, Tuple
|
|
645
|
+
from dataclasses import dataclass, asdict
|
|
646
|
+
from enum import Enum
|
|
647
|
+
import struct
|
|
648
|
+
import queue
|
|
649
|
+
|
|
650
|
+
# Hardware interfaces
|
|
651
|
+
import RPi.GPIO as GPIO
|
|
652
|
+
import spidev
|
|
653
|
+
import serial
|
|
654
|
+
import smbus2
|
|
655
|
+
|
|
656
|
+
# Networking
|
|
657
|
+
import paho.mqtt.client as mqtt
|
|
658
|
+
import modbus_tk.defines as cst
|
|
659
|
+
from modbus_tk import modbus_tcp, modbus_rtu
|
|
660
|
+
import opcua
|
|
661
|
+
from opcua import Server, Client
|
|
662
|
+
import aiocoap
|
|
663
|
+
import websockets
|
|
664
|
+
|
|
665
|
+
# Edge AI
|
|
666
|
+
import tflite_runtime.interpreter as tflite
|
|
667
|
+
import cv2
|
|
668
|
+
|
|
669
|
+
# Cloud SDKs
|
|
670
|
+
from azure.iot.device.aio import IoTHubDeviceClient
|
|
671
|
+
import boto3
|
|
672
|
+
from google.cloud import iot_v1
|
|
673
|
+
|
|
674
|
+
# Configuration
|
|
675
|
+
logging.basicConfig(level=logging.INFO)
|
|
676
|
+
logger = logging.getLogger(__name__)
|
|
677
|
+
|
|
678
|
+
@dataclass
|
|
679
|
+
class DeviceConfig:
|
|
680
|
+
"""Device configuration"""
|
|
681
|
+
device_id: str
|
|
682
|
+
location: str
|
|
683
|
+
capabilities: List[str]
|
|
684
|
+
protocols: List[str]
|
|
685
|
+
cloud_provider: str
|
|
686
|
+
edge_ai_enabled: bool
|
|
687
|
+
|
|
688
|
+
@dataclass
|
|
689
|
+
class SensorReading:
|
|
690
|
+
"""Sensor data structure"""
|
|
691
|
+
sensor_id: str
|
|
692
|
+
timestamp: float
|
|
693
|
+
value: float
|
|
694
|
+
unit: str
|
|
695
|
+
quality: int
|
|
696
|
+
metadata: Dict[str, Any]
|
|
697
|
+
|
|
698
|
+
class Protocol(Enum):
|
|
699
|
+
"""Communication protocols"""
|
|
700
|
+
MODBUS_TCP = "modbus_tcp"
|
|
701
|
+
MODBUS_RTU = "modbus_rtu"
|
|
702
|
+
OPCUA = "opcua"
|
|
703
|
+
MQTT = "mqtt"
|
|
704
|
+
COAP = "coap"
|
|
705
|
+
LORA = "lora"
|
|
706
|
+
|
|
707
|
+
class EdgeGateway:
|
|
708
|
+
"""Industrial IoT Edge Gateway"""
|
|
709
|
+
|
|
710
|
+
def __init__(self, config: DeviceConfig):
|
|
711
|
+
self.config = config
|
|
712
|
+
self.running = False
|
|
713
|
+
|
|
714
|
+
# Hardware setup
|
|
715
|
+
GPIO.setmode(GPIO.BCM)
|
|
716
|
+
self.spi = spidev.SpiDev()
|
|
717
|
+
self.i2c = smbus2.SMBus(1)
|
|
718
|
+
|
|
719
|
+
# Data management
|
|
720
|
+
self.data_queue = queue.Queue(maxsize=10000)
|
|
721
|
+
self.event_queue = queue.Queue(maxsize=1000)
|
|
722
|
+
self.db_conn = self._init_database()
|
|
723
|
+
|
|
724
|
+
# Protocol handlers
|
|
725
|
+
self.protocol_handlers = {}
|
|
726
|
+
self._init_protocols()
|
|
727
|
+
|
|
728
|
+
# Edge AI
|
|
729
|
+
if config.edge_ai_enabled:
|
|
730
|
+
self.ai_engine = EdgeAIEngine()
|
|
731
|
+
|
|
732
|
+
# Cloud connectivity
|
|
733
|
+
self.cloud_client = self._init_cloud_client()
|
|
734
|
+
|
|
735
|
+
def _init_database(self) -> sqlite3.Connection:
|
|
736
|
+
"""Initialize local database for buffering"""
|
|
737
|
+
conn = sqlite3.connect('gateway_data.db', check_same_thread=False)
|
|
738
|
+
cursor = conn.cursor()
|
|
739
|
+
|
|
740
|
+
cursor.execute('''
|
|
741
|
+
CREATE TABLE IF NOT EXISTS sensor_data (
|
|
742
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
743
|
+
sensor_id TEXT NOT NULL,
|
|
744
|
+
timestamp REAL NOT NULL,
|
|
745
|
+
value REAL NOT NULL,
|
|
746
|
+
unit TEXT,
|
|
747
|
+
quality INTEGER,
|
|
748
|
+
metadata TEXT,
|
|
749
|
+
synced BOOLEAN DEFAULT FALSE,
|
|
750
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
751
|
+
)
|
|
752
|
+
''')
|
|
753
|
+
|
|
754
|
+
cursor.execute('''
|
|
755
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
756
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
757
|
+
event_type TEXT NOT NULL,
|
|
758
|
+
severity TEXT NOT NULL,
|
|
759
|
+
source TEXT NOT NULL,
|
|
760
|
+
message TEXT,
|
|
761
|
+
data TEXT,
|
|
762
|
+
acknowledged BOOLEAN DEFAULT FALSE,
|
|
763
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
764
|
+
)
|
|
765
|
+
''')
|
|
766
|
+
|
|
767
|
+
conn.commit()
|
|
768
|
+
return conn
|
|
769
|
+
|
|
770
|
+
def _init_protocols(self):
|
|
771
|
+
"""Initialize protocol handlers"""
|
|
772
|
+
if Protocol.MODBUS_TCP.value in self.config.protocols:
|
|
773
|
+
self.protocol_handlers[Protocol.MODBUS_TCP] = ModbusTCPHandler()
|
|
774
|
+
|
|
775
|
+
if Protocol.MODBUS_RTU.value in self.config.protocols:
|
|
776
|
+
self.protocol_handlers[Protocol.MODBUS_RTU] = ModbusRTUHandler('/dev/ttyUSB0')
|
|
777
|
+
|
|
778
|
+
if Protocol.OPCUA.value in self.config.protocols:
|
|
779
|
+
self.protocol_handlers[Protocol.OPCUA] = OPCUAHandler()
|
|
780
|
+
|
|
781
|
+
if Protocol.MQTT.value in self.config.protocols:
|
|
782
|
+
self.protocol_handlers[Protocol.MQTT] = MQTTHandler()
|
|
783
|
+
|
|
784
|
+
if Protocol.LORA.value in self.config.protocols:
|
|
785
|
+
self.protocol_handlers[Protocol.LORA] = LoRaHandler()
|
|
786
|
+
|
|
787
|
+
def _init_cloud_client(self):
|
|
788
|
+
"""Initialize cloud client based on provider"""
|
|
789
|
+
if self.config.cloud_provider == "azure":
|
|
790
|
+
return AzureIoTClient(self.config.device_id)
|
|
791
|
+
elif self.config.cloud_provider == "aws":
|
|
792
|
+
return AWSIoTClient(self.config.device_id)
|
|
793
|
+
elif self.config.cloud_provider == "gcp":
|
|
794
|
+
return GCPIoTClient(self.config.device_id)
|
|
795
|
+
else:
|
|
796
|
+
return None
|
|
797
|
+
|
|
798
|
+
class ModbusTCPHandler:
|
|
799
|
+
"""Modbus TCP protocol handler"""
|
|
800
|
+
|
|
801
|
+
def __init__(self, host='0.0.0.0', port=502):
|
|
802
|
+
self.master = modbus_tcp.TcpMaster(host, port)
|
|
803
|
+
self.master.set_timeout(5.0)
|
|
804
|
+
|
|
805
|
+
async def read_registers(self, slave_id: int, start_addr: int,
|
|
806
|
+
count: int) -> List[int]:
|
|
807
|
+
"""Read holding registers"""
|
|
808
|
+
try:
|
|
809
|
+
return self.master.execute(
|
|
810
|
+
slave_id,
|
|
811
|
+
cst.READ_HOLDING_REGISTERS,
|
|
812
|
+
start_addr,
|
|
813
|
+
count
|
|
814
|
+
)
|
|
815
|
+
except Exception as e:
|
|
816
|
+
logger.error(f"Modbus read error: {e}")
|
|
817
|
+
return []
|
|
818
|
+
|
|
819
|
+
async def write_register(self, slave_id: int, addr: int, value: int):
|
|
820
|
+
"""Write single register"""
|
|
821
|
+
try:
|
|
822
|
+
self.master.execute(
|
|
823
|
+
slave_id,
|
|
824
|
+
cst.WRITE_SINGLE_REGISTER,
|
|
825
|
+
addr,
|
|
826
|
+
output_value=value
|
|
827
|
+
)
|
|
828
|
+
except Exception as e:
|
|
829
|
+
logger.error(f"Modbus write error: {e}")
|
|
830
|
+
|
|
831
|
+
class ModbusRTUHandler:
|
|
832
|
+
"""Modbus RTU protocol handler"""
|
|
833
|
+
|
|
834
|
+
def __init__(self, port: str, baudrate: int = 9600):
|
|
835
|
+
self.serial = serial.Serial(
|
|
836
|
+
port=port,
|
|
837
|
+
baudrate=baudrate,
|
|
838
|
+
bytesize=8,
|
|
839
|
+
parity='N',
|
|
840
|
+
stopbits=1,
|
|
841
|
+
timeout=1
|
|
842
|
+
)
|
|
843
|
+
self.master = modbus_rtu.RtuMaster(self.serial)
|
|
844
|
+
self.master.set_timeout(5.0)
|
|
845
|
+
|
|
846
|
+
def read_input_registers(self, slave_id: int, start_addr: int,
|
|
847
|
+
count: int) -> List[int]:
|
|
848
|
+
"""Read input registers"""
|
|
849
|
+
try:
|
|
850
|
+
return self.master.execute(
|
|
851
|
+
slave_id,
|
|
852
|
+
cst.READ_INPUT_REGISTERS,
|
|
853
|
+
start_addr,
|
|
854
|
+
count
|
|
855
|
+
)
|
|
856
|
+
except Exception as e:
|
|
857
|
+
logger.error(f"Modbus RTU error: {e}")
|
|
858
|
+
return []
|
|
859
|
+
|
|
860
|
+
class OPCUAHandler:
|
|
861
|
+
"""OPC UA protocol handler"""
|
|
862
|
+
|
|
863
|
+
def __init__(self):
|
|
864
|
+
self.server = Server()
|
|
865
|
+
self.server.set_endpoint("opc.tcp://0.0.0.0:4840")
|
|
866
|
+
self.server.set_server_name("Industrial IoT Gateway")
|
|
867
|
+
|
|
868
|
+
# Setup namespace
|
|
869
|
+
uri = "http://industrial.iot.gateway"
|
|
870
|
+
self.idx = self.server.register_namespace(uri)
|
|
871
|
+
|
|
872
|
+
# Create objects
|
|
873
|
+
self.objects = self.server.get_objects_node()
|
|
874
|
+
self.device = self.objects.add_object(self.idx, "Gateway")
|
|
875
|
+
|
|
876
|
+
async def start(self):
|
|
877
|
+
"""Start OPC UA server"""
|
|
878
|
+
self.server.start()
|
|
879
|
+
logger.info("OPC UA server started")
|
|
880
|
+
|
|
881
|
+
async def add_variable(self, name: str, value: Any) -> opcua.Node:
|
|
882
|
+
"""Add a variable to the server"""
|
|
883
|
+
var = self.device.add_variable(self.idx, name, value)
|
|
884
|
+
var.set_writable()
|
|
885
|
+
return var
|
|
886
|
+
|
|
887
|
+
async def update_variable(self, node: opcua.Node, value: Any):
|
|
888
|
+
"""Update variable value"""
|
|
889
|
+
node.set_value(value)
|
|
890
|
+
|
|
891
|
+
class MQTTHandler:
|
|
892
|
+
"""MQTT protocol handler with QoS and persistence"""
|
|
893
|
+
|
|
894
|
+
def __init__(self, broker: str = "localhost", port: int = 1883):
|
|
895
|
+
self.client = mqtt.Client(client_id=f"gateway_{int(time.time())}")
|
|
896
|
+
self.broker = broker
|
|
897
|
+
self.port = port
|
|
898
|
+
self.connected = False
|
|
899
|
+
|
|
900
|
+
# Callbacks
|
|
901
|
+
self.client.on_connect = self._on_connect
|
|
902
|
+
self.client.on_disconnect = self._on_disconnect
|
|
903
|
+
self.client.on_message = self._on_message
|
|
904
|
+
|
|
905
|
+
# Message buffer for offline operation
|
|
906
|
+
self.message_buffer = []
|
|
907
|
+
|
|
908
|
+
def _on_connect(self, client, userdata, flags, rc):
|
|
909
|
+
"""Connection callback"""
|
|
910
|
+
if rc == 0:
|
|
911
|
+
self.connected = True
|
|
912
|
+
logger.info("MQTT connected")
|
|
913
|
+
|
|
914
|
+
# Flush buffered messages
|
|
915
|
+
for msg in self.message_buffer:
|
|
916
|
+
self.publish(msg['topic'], msg['payload'], msg['qos'])
|
|
917
|
+
self.message_buffer.clear()
|
|
918
|
+
else:
|
|
919
|
+
logger.error(f"MQTT connection failed: {rc}")
|
|
920
|
+
|
|
921
|
+
def _on_disconnect(self, client, userdata, rc):
|
|
922
|
+
"""Disconnection callback"""
|
|
923
|
+
self.connected = False
|
|
924
|
+
logger.warning("MQTT disconnected")
|
|
925
|
+
|
|
926
|
+
def _on_message(self, client, userdata, msg):
|
|
927
|
+
"""Message callback"""
|
|
928
|
+
try:
|
|
929
|
+
payload = json.loads(msg.payload.decode())
|
|
930
|
+
logger.info(f"MQTT message received: {msg.topic}")
|
|
931
|
+
# Process message
|
|
932
|
+
except Exception as e:
|
|
933
|
+
logger.error(f"MQTT message error: {e}")
|
|
934
|
+
|
|
935
|
+
async def connect(self):
|
|
936
|
+
"""Connect to broker"""
|
|
937
|
+
try:
|
|
938
|
+
self.client.connect(self.broker, self.port, 60)
|
|
939
|
+
self.client.loop_start()
|
|
940
|
+
except Exception as e:
|
|
941
|
+
logger.error(f"MQTT connection error: {e}")
|
|
942
|
+
|
|
943
|
+
def publish(self, topic: str, payload: Dict, qos: int = 1):
|
|
944
|
+
"""Publish message with QoS"""
|
|
945
|
+
if self.connected:
|
|
946
|
+
self.client.publish(
|
|
947
|
+
topic,
|
|
948
|
+
json.dumps(payload),
|
|
949
|
+
qos=qos,
|
|
950
|
+
retain=False
|
|
951
|
+
)
|
|
952
|
+
else:
|
|
953
|
+
# Buffer for later
|
|
954
|
+
self.message_buffer.append({
|
|
955
|
+
'topic': topic,
|
|
956
|
+
'payload': payload,
|
|
957
|
+
'qos': qos
|
|
958
|
+
})
|
|
959
|
+
|
|
960
|
+
class LoRaHandler:
|
|
961
|
+
"""LoRa/LoRaWAN handler for long-range communication"""
|
|
962
|
+
|
|
963
|
+
def __init__(self, spi_bus: int = 0, spi_device: int = 0):
|
|
964
|
+
# LoRa module configuration (e.g., SX1276)
|
|
965
|
+
self.spi = spidev.SpiDev()
|
|
966
|
+
self.spi.open(spi_bus, spi_device)
|
|
967
|
+
self.spi.max_speed_hz = 50000
|
|
968
|
+
|
|
969
|
+
# GPIO pins
|
|
970
|
+
self.RESET_PIN = 17
|
|
971
|
+
self.DIO0_PIN = 4
|
|
972
|
+
|
|
973
|
+
GPIO.setup(self.RESET_PIN, GPIO.OUT)
|
|
974
|
+
GPIO.setup(self.DIO0_PIN, GPIO.IN)
|
|
975
|
+
|
|
976
|
+
self._init_lora()
|
|
977
|
+
|
|
978
|
+
def _init_lora(self):
|
|
979
|
+
"""Initialize LoRa module"""
|
|
980
|
+
# Reset module
|
|
981
|
+
GPIO.output(self.RESET_PIN, GPIO.LOW)
|
|
982
|
+
time.sleep(0.01)
|
|
983
|
+
GPIO.output(self.RESET_PIN, GPIO.HIGH)
|
|
984
|
+
time.sleep(0.01)
|
|
985
|
+
|
|
986
|
+
# Configure registers
|
|
987
|
+
self._write_register(0x01, 0x80) # Sleep mode
|
|
988
|
+
self._write_register(0x01, 0x81) # LoRa mode
|
|
989
|
+
|
|
990
|
+
# Set frequency (868 MHz)
|
|
991
|
+
freq = int(868000000 / 61.035)
|
|
992
|
+
self._write_register(0x06, (freq >> 16) & 0xFF)
|
|
993
|
+
self._write_register(0x07, (freq >> 8) & 0xFF)
|
|
994
|
+
self._write_register(0x08, freq & 0xFF)
|
|
995
|
+
|
|
996
|
+
# Set spreading factor, bandwidth, coding rate
|
|
997
|
+
self._write_register(0x1D, 0x72) # SF7, BW125, CR4/5
|
|
998
|
+
self._write_register(0x1E, 0x74) # SF7, CRC on
|
|
999
|
+
|
|
1000
|
+
def _write_register(self, addr: int, value: int):
|
|
1001
|
+
"""Write to LoRa register"""
|
|
1002
|
+
self.spi.xfer2([addr | 0x80, value])
|
|
1003
|
+
|
|
1004
|
+
def _read_register(self, addr: int) -> int:
|
|
1005
|
+
"""Read from LoRa register"""
|
|
1006
|
+
result = self.spi.xfer2([addr & 0x7F, 0x00])
|
|
1007
|
+
return result[1]
|
|
1008
|
+
|
|
1009
|
+
def send_packet(self, data: bytes):
|
|
1010
|
+
"""Send LoRa packet"""
|
|
1011
|
+
# Set to standby mode
|
|
1012
|
+
self._write_register(0x01, 0x81)
|
|
1013
|
+
|
|
1014
|
+
# Set FIFO pointer
|
|
1015
|
+
self._write_register(0x0D, 0x80)
|
|
1016
|
+
|
|
1017
|
+
# Write data to FIFO
|
|
1018
|
+
for byte in data:
|
|
1019
|
+
self._write_register(0x00, byte)
|
|
1020
|
+
|
|
1021
|
+
# Set payload length
|
|
1022
|
+
self._write_register(0x22, len(data))
|
|
1023
|
+
|
|
1024
|
+
# Start transmission
|
|
1025
|
+
self._write_register(0x01, 0x83)
|
|
1026
|
+
|
|
1027
|
+
# Wait for transmission complete
|
|
1028
|
+
while not GPIO.input(self.DIO0_PIN):
|
|
1029
|
+
time.sleep(0.001)
|
|
1030
|
+
|
|
1031
|
+
def receive_packet(self) -> Optional[bytes]:
|
|
1032
|
+
"""Receive LoRa packet"""
|
|
1033
|
+
# Check for packet
|
|
1034
|
+
if GPIO.input(self.DIO0_PIN):
|
|
1035
|
+
# Get packet length
|
|
1036
|
+
length = self._read_register(0x13)
|
|
1037
|
+
|
|
1038
|
+
# Set FIFO pointer
|
|
1039
|
+
current_addr = self._read_register(0x10)
|
|
1040
|
+
self._write_register(0x0D, current_addr)
|
|
1041
|
+
|
|
1042
|
+
# Read packet
|
|
1043
|
+
packet = []
|
|
1044
|
+
for _ in range(length):
|
|
1045
|
+
packet.append(self._read_register(0x00))
|
|
1046
|
+
|
|
1047
|
+
# Clear IRQ
|
|
1048
|
+
self._write_register(0x12, 0xFF)
|
|
1049
|
+
|
|
1050
|
+
return bytes(packet)
|
|
1051
|
+
|
|
1052
|
+
return None
|
|
1053
|
+
|
|
1054
|
+
class EdgeAIEngine:
|
|
1055
|
+
"""Edge AI processing engine"""
|
|
1056
|
+
|
|
1057
|
+
def __init__(self):
|
|
1058
|
+
self.models = {}
|
|
1059
|
+
self.load_models()
|
|
1060
|
+
|
|
1061
|
+
def load_models(self):
|
|
1062
|
+
"""Load TensorFlow Lite models"""
|
|
1063
|
+
# Anomaly detection model
|
|
1064
|
+
self.models['anomaly'] = tflite.Interpreter(
|
|
1065
|
+
model_path='/opt/models/anomaly_detection.tflite'
|
|
1066
|
+
)
|
|
1067
|
+
self.models['anomaly'].allocate_tensors()
|
|
1068
|
+
|
|
1069
|
+
# Predictive maintenance model
|
|
1070
|
+
self.models['maintenance'] = tflite.Interpreter(
|
|
1071
|
+
model_path='/opt/models/predictive_maintenance.tflite'
|
|
1072
|
+
)
|
|
1073
|
+
self.models['maintenance'].allocate_tensors()
|
|
1074
|
+
|
|
1075
|
+
def detect_anomaly(self, data: np.ndarray) -> Tuple[bool, float]:
|
|
1076
|
+
"""Detect anomalies in sensor data"""
|
|
1077
|
+
interpreter = self.models['anomaly']
|
|
1078
|
+
input_details = interpreter.get_input_details()
|
|
1079
|
+
output_details = interpreter.get_output_details()
|
|
1080
|
+
|
|
1081
|
+
# Preprocess data
|
|
1082
|
+
input_data = np.array(data, dtype=np.float32).reshape(1, -1)
|
|
1083
|
+
|
|
1084
|
+
# Run inference
|
|
1085
|
+
interpreter.set_tensor(input_details[0]['index'], input_data)
|
|
1086
|
+
interpreter.invoke()
|
|
1087
|
+
|
|
1088
|
+
# Get results
|
|
1089
|
+
output_data = interpreter.get_tensor(output_details[0]['index'])
|
|
1090
|
+
anomaly_score = float(output_data[0][0])
|
|
1091
|
+
|
|
1092
|
+
return anomaly_score > 0.7, anomaly_score
|
|
1093
|
+
|
|
1094
|
+
def predict_maintenance(self, sensor_history: np.ndarray) -> Dict[str, Any]:
|
|
1095
|
+
"""Predict maintenance requirements"""
|
|
1096
|
+
interpreter = self.models['maintenance']
|
|
1097
|
+
input_details = interpreter.get_input_details()
|
|
1098
|
+
output_details = interpreter.get_output_details()
|
|
1099
|
+
|
|
1100
|
+
# Prepare input
|
|
1101
|
+
input_data = sensor_history.astype(np.float32).reshape(1, -1)
|
|
1102
|
+
|
|
1103
|
+
# Run inference
|
|
1104
|
+
interpreter.set_tensor(input_details[0]['index'], input_data)
|
|
1105
|
+
interpreter.invoke()
|
|
1106
|
+
|
|
1107
|
+
# Get results
|
|
1108
|
+
output_data = interpreter.get_tensor(output_details[0]['index'])
|
|
1109
|
+
|
|
1110
|
+
return {
|
|
1111
|
+
'failure_probability': float(output_data[0][0]),
|
|
1112
|
+
'estimated_days_to_failure': int(output_data[0][1]),
|
|
1113
|
+
'recommended_action': self._get_maintenance_action(output_data[0][2])
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
def _get_maintenance_action(self, action_code: int) -> str:
|
|
1117
|
+
"""Map action code to recommendation"""
|
|
1118
|
+
actions = {
|
|
1119
|
+
0: "No action required",
|
|
1120
|
+
1: "Schedule routine maintenance",
|
|
1121
|
+
2: "Inspect component",
|
|
1122
|
+
3: "Replace component immediately"
|
|
1123
|
+
}
|
|
1124
|
+
return actions.get(action_code, "Unknown")
|
|
1125
|
+
|
|
1126
|
+
class DataProcessor:
|
|
1127
|
+
"""Real-time data processing and aggregation"""
|
|
1128
|
+
|
|
1129
|
+
def __init__(self, window_size: int = 100):
|
|
1130
|
+
self.window_size = window_size
|
|
1131
|
+
self.data_windows = {}
|
|
1132
|
+
|
|
1133
|
+
def add_sample(self, sensor_id: str, value: float):
|
|
1134
|
+
"""Add sample to processing window"""
|
|
1135
|
+
if sensor_id not in self.data_windows:
|
|
1136
|
+
self.data_windows[sensor_id] = []
|
|
1137
|
+
|
|
1138
|
+
window = self.data_windows[sensor_id]
|
|
1139
|
+
window.append(value)
|
|
1140
|
+
|
|
1141
|
+
if len(window) > self.window_size:
|
|
1142
|
+
window.pop(0)
|
|
1143
|
+
|
|
1144
|
+
def calculate_statistics(self, sensor_id: str) -> Dict[str, float]:
|
|
1145
|
+
"""Calculate statistics for sensor"""
|
|
1146
|
+
if sensor_id not in self.data_windows:
|
|
1147
|
+
return {}
|
|
1148
|
+
|
|
1149
|
+
window = np.array(self.data_windows[sensor_id])
|
|
1150
|
+
|
|
1151
|
+
return {
|
|
1152
|
+
'mean': np.mean(window),
|
|
1153
|
+
'std': np.std(window),
|
|
1154
|
+
'min': np.min(window),
|
|
1155
|
+
'max': np.max(window),
|
|
1156
|
+
'median': np.median(window),
|
|
1157
|
+
'trend': self._calculate_trend(window)
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
def _calculate_trend(self, data: np.ndarray) -> float:
|
|
1161
|
+
"""Calculate trend using linear regression"""
|
|
1162
|
+
if len(data) < 2:
|
|
1163
|
+
return 0.0
|
|
1164
|
+
|
|
1165
|
+
x = np.arange(len(data))
|
|
1166
|
+
coeffs = np.polyfit(x, data, 1)
|
|
1167
|
+
return coeffs[0]
|
|
1168
|
+
|
|
1169
|
+
# Main execution
|
|
1170
|
+
async def main():
|
|
1171
|
+
"""Main gateway execution"""
|
|
1172
|
+
config = DeviceConfig(
|
|
1173
|
+
device_id="RPI_GATEWAY_001",
|
|
1174
|
+
location="Factory Floor A",
|
|
1175
|
+
capabilities=["modbus", "opcua", "mqtt", "lora", "edge_ai"],
|
|
1176
|
+
protocols=["modbus_tcp", "opcua", "mqtt", "lora"],
|
|
1177
|
+
cloud_provider="azure",
|
|
1178
|
+
edge_ai_enabled=True
|
|
1179
|
+
)
|
|
1180
|
+
|
|
1181
|
+
gateway = EdgeGateway(config)
|
|
1182
|
+
|
|
1183
|
+
try:
|
|
1184
|
+
# Start gateway
|
|
1185
|
+
await gateway.start()
|
|
1186
|
+
|
|
1187
|
+
# Run forever
|
|
1188
|
+
while True:
|
|
1189
|
+
await asyncio.sleep(1)
|
|
1190
|
+
|
|
1191
|
+
except KeyboardInterrupt:
|
|
1192
|
+
logger.info("Shutting down gateway...")
|
|
1193
|
+
await gateway.stop()
|
|
1194
|
+
finally:
|
|
1195
|
+
GPIO.cleanup()
|
|
1196
|
+
|
|
1197
|
+
if __name__ == "__main__":
|
|
1198
|
+
asyncio.run(main())
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
### STM32 Real-Time Control System (C)
|
|
1202
|
+
```c
|
|
1203
|
+
/**
|
|
1204
|
+
* STM32F4 Real-Time Industrial Control System
|
|
1205
|
+
* Bare-metal implementation with FreeRTOS
|
|
1206
|
+
*/
|
|
1207
|
+
|
|
1208
|
+
#include "stm32f4xx.h"
|
|
1209
|
+
#include "FreeRTOS.h"
|
|
1210
|
+
#include "task.h"
|
|
1211
|
+
#include "queue.h"
|
|
1212
|
+
#include "semphr.h"
|
|
1213
|
+
#include "timers.h"
|
|
1214
|
+
#include <string.h>
|
|
1215
|
+
#include <math.h>
|
|
1216
|
+
|
|
1217
|
+
// Hardware Configuration
|
|
1218
|
+
#define LED_PIN GPIO_PIN_13
|
|
1219
|
+
#define SENSOR_ADC_CH ADC_CHANNEL_0
|
|
1220
|
+
#define PWM_TIM TIM2
|
|
1221
|
+
#define UART_BAUDRATE 115200
|
|
1222
|
+
#define CAN_BITRATE 500000
|
|
1223
|
+
|
|
1224
|
+
// Task Priorities
|
|
1225
|
+
#define PRIORITY_CRITICAL (configMAX_PRIORITIES - 1)
|
|
1226
|
+
#define PRIORITY_HIGH (configMAX_PRIORITIES - 2)
|
|
1227
|
+
#define PRIORITY_NORMAL (configMAX_PRIORITIES - 3)
|
|
1228
|
+
#define PRIORITY_LOW (configMAX_PRIORITIES - 4)
|
|
1229
|
+
|
|
1230
|
+
// System Configuration
|
|
1231
|
+
typedef struct {
|
|
1232
|
+
uint32_t device_id;
|
|
1233
|
+
uint32_t sample_rate_hz;
|
|
1234
|
+
uint32_t control_period_ms;
|
|
1235
|
+
float setpoint;
|
|
1236
|
+
float kp, ki, kd; // PID parameters
|
|
1237
|
+
uint8_t safety_enabled;
|
|
1238
|
+
} SystemConfig_t;
|
|
1239
|
+
|
|
1240
|
+
// Sensor Data Structure
|
|
1241
|
+
typedef struct {
|
|
1242
|
+
uint32_t timestamp;
|
|
1243
|
+
float temperature;
|
|
1244
|
+
float pressure;
|
|
1245
|
+
float flow_rate;
|
|
1246
|
+
float voltage;
|
|
1247
|
+
float current;
|
|
1248
|
+
uint8_t status;
|
|
1249
|
+
} SensorData_t;
|
|
1250
|
+
|
|
1251
|
+
// Control Output
|
|
1252
|
+
typedef struct {
|
|
1253
|
+
float pwm_duty;
|
|
1254
|
+
uint8_t relay_state;
|
|
1255
|
+
float valve_position;
|
|
1256
|
+
uint32_t error_code;
|
|
1257
|
+
} ControlOutput_t;
|
|
1258
|
+
|
|
1259
|
+
// Global handles
|
|
1260
|
+
static QueueHandle_t xSensorQueue;
|
|
1261
|
+
static QueueHandle_t xControlQueue;
|
|
1262
|
+
static SemaphoreHandle_t xI2CMutex;
|
|
1263
|
+
static SemaphoreHandle_t xCANMutex;
|
|
1264
|
+
static TimerHandle_t xWatchdogTimer;
|
|
1265
|
+
|
|
1266
|
+
// DMA buffers
|
|
1267
|
+
__attribute__((aligned(4))) static uint16_t adc_dma_buffer[16];
|
|
1268
|
+
__attribute__((aligned(4))) static uint8_t uart_rx_buffer[256];
|
|
1269
|
+
__attribute__((aligned(4))) static uint8_t uart_tx_buffer[256];
|
|
1270
|
+
|
|
1271
|
+
// PID Controller
|
|
1272
|
+
typedef struct {
|
|
1273
|
+
float kp, ki, kd;
|
|
1274
|
+
float integral;
|
|
1275
|
+
float prev_error;
|
|
1276
|
+
float output_min, output_max;
|
|
1277
|
+
uint32_t last_time;
|
|
1278
|
+
} PIDController_t;
|
|
1279
|
+
|
|
1280
|
+
static PIDController_t pid_controller = {
|
|
1281
|
+
.kp = 2.0f,
|
|
1282
|
+
.ki = 0.5f,
|
|
1283
|
+
.kd = 0.1f,
|
|
1284
|
+
.output_min = 0.0f,
|
|
1285
|
+
.output_max = 100.0f
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
// Function prototypes
|
|
1289
|
+
static void SystemClock_Config(void);
|
|
1290
|
+
static void GPIO_Init(void);
|
|
1291
|
+
static void ADC_Init(void);
|
|
1292
|
+
static void UART_Init(void);
|
|
1293
|
+
static void CAN_Init(void);
|
|
1294
|
+
static void I2C_Init(void);
|
|
1295
|
+
static void TIM_PWM_Init(void);
|
|
1296
|
+
static void DMA_Init(void);
|
|
1297
|
+
static void NVIC_Init(void);
|
|
1298
|
+
|
|
1299
|
+
// Task prototypes
|
|
1300
|
+
static void vSensorTask(void *pvParameters);
|
|
1301
|
+
static void vControlTask(void *pvParameters);
|
|
1302
|
+
static void vCommunicationTask(void *pvParameters);
|
|
1303
|
+
static void vSafetyTask(void *pvParameters);
|
|
1304
|
+
static void vDiagnosticsTask(void *pvParameters);
|
|
1305
|
+
|
|
1306
|
+
// Interrupt handlers
|
|
1307
|
+
void ADC_IRQHandler(void);
|
|
1308
|
+
void DMA2_Stream0_IRQHandler(void);
|
|
1309
|
+
void CAN1_RX0_IRQHandler(void);
|
|
1310
|
+
void USART1_IRQHandler(void);
|
|
1311
|
+
void TIM2_IRQHandler(void);
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Main entry point
|
|
1315
|
+
*/
|
|
1316
|
+
int main(void) {
|
|
1317
|
+
// Initialize HAL and system
|
|
1318
|
+
HAL_Init();
|
|
1319
|
+
SystemClock_Config();
|
|
1320
|
+
|
|
1321
|
+
// Initialize peripherals
|
|
1322
|
+
GPIO_Init();
|
|
1323
|
+
ADC_Init();
|
|
1324
|
+
UART_Init();
|
|
1325
|
+
CAN_Init();
|
|
1326
|
+
I2C_Init();
|
|
1327
|
+
TIM_PWM_Init();
|
|
1328
|
+
DMA_Init();
|
|
1329
|
+
NVIC_Init();
|
|
1330
|
+
|
|
1331
|
+
// Create FreeRTOS objects
|
|
1332
|
+
xSensorQueue = xQueueCreate(10, sizeof(SensorData_t));
|
|
1333
|
+
xControlQueue = xQueueCreate(5, sizeof(ControlOutput_t));
|
|
1334
|
+
xI2CMutex = xSemaphoreCreateMutex();
|
|
1335
|
+
xCANMutex = xSemaphoreCreateMutex();
|
|
1336
|
+
|
|
1337
|
+
// Create watchdog timer
|
|
1338
|
+
xWatchdogTimer = xTimerCreate(
|
|
1339
|
+
"Watchdog",
|
|
1340
|
+
pdMS_TO_TICKS(1000),
|
|
1341
|
+
pdTRUE,
|
|
1342
|
+
NULL,
|
|
1343
|
+
vWatchdogCallback
|
|
1344
|
+
);
|
|
1345
|
+
|
|
1346
|
+
// Create tasks
|
|
1347
|
+
xTaskCreate(vSensorTask, "Sensor", 512, NULL, PRIORITY_HIGH, NULL);
|
|
1348
|
+
xTaskCreate(vControlTask, "Control", 768, NULL, PRIORITY_CRITICAL, NULL);
|
|
1349
|
+
xTaskCreate(vCommunicationTask, "Comm", 1024, NULL, PRIORITY_NORMAL, NULL);
|
|
1350
|
+
xTaskCreate(vSafetyTask, "Safety", 256, NULL, PRIORITY_CRITICAL, NULL);
|
|
1351
|
+
xTaskCreate(vDiagnosticsTask, "Diag", 512, NULL, PRIORITY_LOW, NULL);
|
|
1352
|
+
|
|
1353
|
+
// Start watchdog timer
|
|
1354
|
+
xTimerStart(xWatchdogTimer, 0);
|
|
1355
|
+
|
|
1356
|
+
// Start scheduler
|
|
1357
|
+
vTaskStartScheduler();
|
|
1358
|
+
|
|
1359
|
+
// Should never reach here
|
|
1360
|
+
while(1);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
/**
|
|
1364
|
+
* Sensor acquisition task - runs every 10ms
|
|
1365
|
+
*/
|
|
1366
|
+
static void vSensorTask(void *pvParameters) {
|
|
1367
|
+
SensorData_t sensor_data;
|
|
1368
|
+
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
1369
|
+
const TickType_t xPeriod = pdMS_TO_TICKS(10);
|
|
1370
|
+
|
|
1371
|
+
for(;;) {
|
|
1372
|
+
// Wait for precise timing
|
|
1373
|
+
vTaskDelayUntil(&xLastWakeTime, xPeriod);
|
|
1374
|
+
|
|
1375
|
+
// Read ADC channels via DMA
|
|
1376
|
+
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buffer, 16);
|
|
1377
|
+
|
|
1378
|
+
// Get timestamp
|
|
1379
|
+
sensor_data.timestamp = HAL_GetTick();
|
|
1380
|
+
|
|
1381
|
+
// Process ADC readings with calibration
|
|
1382
|
+
sensor_data.temperature = adc_to_temperature(adc_dma_buffer[0]);
|
|
1383
|
+
sensor_data.pressure = adc_to_pressure(adc_dma_buffer[1]);
|
|
1384
|
+
sensor_data.flow_rate = adc_to_flow(adc_dma_buffer[2]);
|
|
1385
|
+
sensor_data.voltage = adc_to_voltage(adc_dma_buffer[3]);
|
|
1386
|
+
sensor_data.current = adc_to_current(adc_dma_buffer[4]);
|
|
1387
|
+
|
|
1388
|
+
// Read I2C sensors (with mutex protection)
|
|
1389
|
+
if(xSemaphoreTake(xI2CMutex, pdMS_TO_TICKS(5)) == pdTRUE) {
|
|
1390
|
+
read_i2c_sensor(&sensor_data);
|
|
1391
|
+
xSemaphoreGive(xI2CMutex);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// Apply digital filtering (moving average)
|
|
1395
|
+
apply_filter(&sensor_data);
|
|
1396
|
+
|
|
1397
|
+
// Check sensor validity
|
|
1398
|
+
sensor_data.status = validate_sensors(&sensor_data);
|
|
1399
|
+
|
|
1400
|
+
// Send to control task
|
|
1401
|
+
xQueueSend(xSensorQueue, &sensor_data, 0);
|
|
1402
|
+
|
|
1403
|
+
// Toggle heartbeat LED
|
|
1404
|
+
HAL_GPIO_TogglePin(GPIOC, LED_PIN);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
/**
|
|
1409
|
+
* Control algorithm task - PID control loop
|
|
1410
|
+
*/
|
|
1411
|
+
static void vControlTask(void *pvParameters) {
|
|
1412
|
+
SensorData_t sensor_data;
|
|
1413
|
+
ControlOutput_t control_output;
|
|
1414
|
+
float setpoint = 50.0f; // Target temperature
|
|
1415
|
+
|
|
1416
|
+
for(;;) {
|
|
1417
|
+
// Wait for sensor data
|
|
1418
|
+
if(xQueueReceive(xSensorQueue, &sensor_data, pdMS_TO_TICKS(100))) {
|
|
1419
|
+
|
|
1420
|
+
// Run PID control algorithm
|
|
1421
|
+
float error = setpoint - sensor_data.temperature;
|
|
1422
|
+
control_output.pwm_duty = pid_compute(&pid_controller, error);
|
|
1423
|
+
|
|
1424
|
+
// Advanced control logic
|
|
1425
|
+
if(sensor_data.pressure > 100.0f) {
|
|
1426
|
+
control_output.valve_position = calculate_valve_position(
|
|
1427
|
+
sensor_data.pressure,
|
|
1428
|
+
sensor_data.flow_rate
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// Safety checks
|
|
1433
|
+
if(sensor_data.temperature > 80.0f) {
|
|
1434
|
+
control_output.pwm_duty = 0;
|
|
1435
|
+
control_output.error_code = ERROR_OVER_TEMP;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// Update PWM output
|
|
1439
|
+
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1,
|
|
1440
|
+
(uint32_t)(control_output.pwm_duty * 10));
|
|
1441
|
+
|
|
1442
|
+
// Update relay states
|
|
1443
|
+
update_relays(control_output.relay_state);
|
|
1444
|
+
|
|
1445
|
+
// Send control output for logging
|
|
1446
|
+
xQueueSend(xControlQueue, &control_output, 0);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Communication task - handles UART, CAN, and network protocols
|
|
1453
|
+
*/
|
|
1454
|
+
static void vCommunicationTask(void *pvParameters) {
|
|
1455
|
+
uint8_t rx_buffer[128];
|
|
1456
|
+
uint8_t tx_buffer[128];
|
|
1457
|
+
CAN_TxHeaderTypeDef can_tx_header;
|
|
1458
|
+
CAN_RxHeaderTypeDef can_rx_header;
|
|
1459
|
+
uint32_t can_mailbox;
|
|
1460
|
+
|
|
1461
|
+
// Configure CAN filter
|
|
1462
|
+
CAN_FilterTypeDef can_filter;
|
|
1463
|
+
can_filter.FilterBank = 0;
|
|
1464
|
+
can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
|
|
1465
|
+
can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
|
|
1466
|
+
can_filter.FilterIdHigh = 0x0000;
|
|
1467
|
+
can_filter.FilterIdLow = 0x0000;
|
|
1468
|
+
can_filter.FilterMaskIdHigh = 0x0000;
|
|
1469
|
+
can_filter.FilterMaskIdLow = 0x0000;
|
|
1470
|
+
can_filter.FilterFIFOAssignment = CAN_RX_FIFO0;
|
|
1471
|
+
can_filter.FilterActivation = ENABLE;
|
|
1472
|
+
HAL_CAN_ConfigFilter(&hcan1, &can_filter);
|
|
1473
|
+
|
|
1474
|
+
// Start CAN
|
|
1475
|
+
HAL_CAN_Start(&hcan1);
|
|
1476
|
+
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
|
|
1477
|
+
|
|
1478
|
+
for(;;) {
|
|
1479
|
+
// Handle UART communication
|
|
1480
|
+
if(HAL_UART_Receive(&huart1, rx_buffer, 128, 10) == HAL_OK) {
|
|
1481
|
+
process_uart_command(rx_buffer, tx_buffer);
|
|
1482
|
+
HAL_UART_Transmit_DMA(&huart1, tx_buffer, strlen((char*)tx_buffer));
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// Send periodic CAN messages
|
|
1486
|
+
if(xSemaphoreTake(xCANMutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
|
1487
|
+
can_tx_header.StdId = 0x321;
|
|
1488
|
+
can_tx_header.ExtId = 0x01;
|
|
1489
|
+
can_tx_header.RTR = CAN_RTR_DATA;
|
|
1490
|
+
can_tx_header.IDE = CAN_ID_STD;
|
|
1491
|
+
can_tx_header.DLC = 8;
|
|
1492
|
+
|
|
1493
|
+
// Pack sensor data into CAN frame
|
|
1494
|
+
SensorData_t sensor_data;
|
|
1495
|
+
if(xQueuePeek(xSensorQueue, &sensor_data, 0)) {
|
|
1496
|
+
pack_can_data(tx_buffer, &sensor_data);
|
|
1497
|
+
HAL_CAN_AddTxMessage(&hcan1, &can_tx_header, tx_buffer, &can_mailbox);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
xSemaphoreGive(xCANMutex);
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
// Handle Modbus RTU protocol
|
|
1504
|
+
handle_modbus_rtu();
|
|
1505
|
+
|
|
1506
|
+
vTaskDelay(pdMS_TO_TICKS(50));
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Safety monitoring task - critical safety functions
|
|
1512
|
+
*/
|
|
1513
|
+
static void vSafetyTask(void *pvParameters) {
|
|
1514
|
+
uint32_t emergency_stop = 0;
|
|
1515
|
+
uint32_t fault_flags = 0;
|
|
1516
|
+
|
|
1517
|
+
for(;;) {
|
|
1518
|
+
// Check emergency stop button
|
|
1519
|
+
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) {
|
|
1520
|
+
emergency_stop = 1;
|
|
1521
|
+
emergency_shutdown();
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// Monitor critical parameters
|
|
1525
|
+
SensorData_t sensor_data;
|
|
1526
|
+
if(xQueuePeek(xSensorQueue, &sensor_data, 0)) {
|
|
1527
|
+
// Temperature limits
|
|
1528
|
+
if(sensor_data.temperature > 100.0f || sensor_data.temperature < -20.0f) {
|
|
1529
|
+
fault_flags |= FAULT_TEMP_RANGE;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
// Pressure limits
|
|
1533
|
+
if(sensor_data.pressure > 150.0f) {
|
|
1534
|
+
fault_flags |= FAULT_OVERPRESSURE;
|
|
1535
|
+
activate_pressure_relief();
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
// Current limits
|
|
1539
|
+
if(sensor_data.current > 10.0f) {
|
|
1540
|
+
fault_flags |= FAULT_OVERCURRENT;
|
|
1541
|
+
disable_outputs();
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// Watchdog feed
|
|
1546
|
+
HAL_IWDG_Refresh(&hiwdg);
|
|
1547
|
+
|
|
1548
|
+
// Update safety status LEDs
|
|
1549
|
+
update_safety_leds(fault_flags);
|
|
1550
|
+
|
|
1551
|
+
vTaskDelay(pdMS_TO_TICKS(10));
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
/**
|
|
1556
|
+
* PID control computation
|
|
1557
|
+
*/
|
|
1558
|
+
float pid_compute(PIDController_t *pid, float error) {
|
|
1559
|
+
uint32_t now = HAL_GetTick();
|
|
1560
|
+
float dt = (now - pid->last_time) / 1000.0f;
|
|
1561
|
+
|
|
1562
|
+
if(dt <= 0.0f) dt = 0.01f;
|
|
1563
|
+
|
|
1564
|
+
// Proportional term
|
|
1565
|
+
float p_term = pid->kp * error;
|
|
1566
|
+
|
|
1567
|
+
// Integral term with anti-windup
|
|
1568
|
+
pid->integral += error * dt;
|
|
1569
|
+
if(pid->integral > 100.0f) pid->integral = 100.0f;
|
|
1570
|
+
if(pid->integral < -100.0f) pid->integral = -100.0f;
|
|
1571
|
+
float i_term = pid->ki * pid->integral;
|
|
1572
|
+
|
|
1573
|
+
// Derivative term with filter
|
|
1574
|
+
float derivative = (error - pid->prev_error) / dt;
|
|
1575
|
+
float d_term = pid->kd * derivative;
|
|
1576
|
+
|
|
1577
|
+
// Calculate output
|
|
1578
|
+
float output = p_term + i_term + d_term;
|
|
1579
|
+
|
|
1580
|
+
// Clamp output
|
|
1581
|
+
if(output > pid->output_max) output = pid->output_max;
|
|
1582
|
+
if(output < pid->output_min) output = pid->output_min;
|
|
1583
|
+
|
|
1584
|
+
// Update state
|
|
1585
|
+
pid->prev_error = error;
|
|
1586
|
+
pid->last_time = now;
|
|
1587
|
+
|
|
1588
|
+
return output;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
/**
|
|
1592
|
+
* DMA transfer complete callback
|
|
1593
|
+
*/
|
|
1594
|
+
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
|
|
1595
|
+
// ADC conversion complete, data in adc_dma_buffer
|
|
1596
|
+
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
1597
|
+
|
|
1598
|
+
// Notify sensor task
|
|
1599
|
+
vTaskNotifyGiveFromISR(xSensorTaskHandle, &xHigherPriorityTaskWoken);
|
|
1600
|
+
|
|
1601
|
+
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/**
|
|
1605
|
+
* CAN receive callback
|
|
1606
|
+
*/
|
|
1607
|
+
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
|
|
1608
|
+
CAN_RxHeaderTypeDef rx_header;
|
|
1609
|
+
uint8_t rx_data[8];
|
|
1610
|
+
|
|
1611
|
+
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) == HAL_OK) {
|
|
1612
|
+
// Process CAN message based on ID
|
|
1613
|
+
switch(rx_header.StdId) {
|
|
1614
|
+
case 0x100: // Configuration update
|
|
1615
|
+
update_configuration(rx_data);
|
|
1616
|
+
break;
|
|
1617
|
+
case 0x200: // Control command
|
|
1618
|
+
process_control_command(rx_data);
|
|
1619
|
+
break;
|
|
1620
|
+
case 0x300: // Diagnostic request
|
|
1621
|
+
send_diagnostic_response();
|
|
1622
|
+
break;
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/**
|
|
1628
|
+
* Hard fault handler with debugging info
|
|
1629
|
+
*/
|
|
1630
|
+
void HardFault_Handler(void) {
|
|
1631
|
+
// Get stack pointer
|
|
1632
|
+
__asm volatile (
|
|
1633
|
+
"tst lr, #4 \n"
|
|
1634
|
+
"ite eq \n"
|
|
1635
|
+
"mrseq r0, msp \n"
|
|
1636
|
+
"mrsne r0, psp \n"
|
|
1637
|
+
"b hard_fault_handler_c \n"
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
void hard_fault_handler_c(uint32_t *hardfault_args) {
|
|
1642
|
+
volatile uint32_t r0 = hardfault_args[0];
|
|
1643
|
+
volatile uint32_t r1 = hardfault_args[1];
|
|
1644
|
+
volatile uint32_t r2 = hardfault_args[2];
|
|
1645
|
+
volatile uint32_t r3 = hardfault_args[3];
|
|
1646
|
+
volatile uint32_t r12 = hardfault_args[4];
|
|
1647
|
+
volatile uint32_t lr = hardfault_args[5];
|
|
1648
|
+
volatile uint32_t pc = hardfault_args[6];
|
|
1649
|
+
volatile uint32_t psr = hardfault_args[7];
|
|
1650
|
+
|
|
1651
|
+
// Log fault information
|
|
1652
|
+
log_fault_info(pc, lr, psr);
|
|
1653
|
+
|
|
1654
|
+
// Reset system
|
|
1655
|
+
NVIC_SystemReset();
|
|
1656
|
+
}
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
## Best Practices
|
|
1660
|
+
|
|
1661
|
+
### 1. Hardware Design
|
|
1662
|
+
- Use proper power regulation and filtering
|
|
1663
|
+
- Implement hardware watchdogs for safety
|
|
1664
|
+
- Add protection circuits (TVS diodes, optocouplers)
|
|
1665
|
+
- Design for electromagnetic compatibility (EMC)
|
|
1666
|
+
- Include debugging interfaces (JTAG/SWD, UART)
|
|
1667
|
+
|
|
1668
|
+
### 2. Software Architecture
|
|
1669
|
+
- Use RTOS for complex timing requirements
|
|
1670
|
+
- Implement defensive programming techniques
|
|
1671
|
+
- Separate hardware abstraction layers
|
|
1672
|
+
- Use state machines for complex logic
|
|
1673
|
+
- Implement comprehensive error handling
|
|
1674
|
+
|
|
1675
|
+
### 3. Communication
|
|
1676
|
+
- Use checksums/CRC for data integrity
|
|
1677
|
+
- Implement timeout and retry mechanisms
|
|
1678
|
+
- Support multiple protocols for flexibility
|
|
1679
|
+
- Use message queuing for reliability
|
|
1680
|
+
- Implement proper flow control
|
|
1681
|
+
|
|
1682
|
+
### 4. Power Management
|
|
1683
|
+
- Implement sleep modes for battery devices
|
|
1684
|
+
- Use interrupt-driven instead of polling
|
|
1685
|
+
- Optimize peripheral clock speeds
|
|
1686
|
+
- Implement brown-out detection
|
|
1687
|
+
- Use DMA for efficient data transfers
|
|
1688
|
+
|
|
1689
|
+
### 5. Security
|
|
1690
|
+
- Implement secure boot mechanisms
|
|
1691
|
+
- Use encryption for sensitive data
|
|
1692
|
+
- Validate all inputs and commands
|
|
1693
|
+
- Implement access control
|
|
1694
|
+
- Regular firmware updates
|
|
1695
|
+
|
|
1696
|
+
### 6. Testing & Debugging
|
|
1697
|
+
- Use hardware-in-the-loop testing
|
|
1698
|
+
- Implement comprehensive logging
|
|
1699
|
+
- Use logic analyzers and oscilloscopes
|
|
1700
|
+
- Test edge cases and failure modes
|
|
1701
|
+
- Implement remote debugging capabilities
|
|
1702
|
+
|
|
1703
|
+
## Common Patterns
|
|
1704
|
+
|
|
1705
|
+
1. **Producer-Consumer**: Sensor data acquisition and processing
|
|
1706
|
+
2. **State Machine**: Device state management
|
|
1707
|
+
3. **Observer**: Event-driven architecture
|
|
1708
|
+
4. **Command**: Remote control implementation
|
|
1709
|
+
5. **Strategy**: Multiple communication protocols
|
|
1710
|
+
6. **Factory**: Dynamic protocol selection
|
|
1711
|
+
7. **Singleton**: Hardware resource management
|
|
1712
|
+
8. **Decorator**: Protocol layering
|
|
1713
|
+
|
|
1714
|
+
Remember: embedded systems require careful attention to resource constraints, real-time requirements, and reliability. Always consider power consumption, memory usage, and safety in your designs.
|