-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconditional-logic.lotnb
More file actions
147 lines (147 loc) · 29.3 KB
/
conditional-logic.lotnb
File metadata and controls
147 lines (147 loc) · 29.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
[
{
"kind": 1,
"language": "markdown",
"value": "# Conditional Logic - Smart Decision Making\r\n\r\n[⬅️ Previous: Topic Actions](../01-basics/topic-actions.lotnb) | [🏠 Back to Index](../index.lotnb) | [➡️ Next: Basic Models](../03-models/basic-models.lotnb)\r\n\r\n---\r\n\r\n<details>\r\n<summary><strong>Navigation Menu</strong></summary>\r\n\r\n| Section | Tutorials |\r\n|---------|----------|\r\n| **Setup** | [Environment Setup](../00-setup/verify-environment.lotnb) |\r\n| **Basics** | [Timed Actions](../01-basics/timed-actions.lotnb) \\| [Topic Actions](../01-basics/topic-actions.lotnb) |\r\n| **Logic** | [Conditional Logic](./conditional-logic.lotnb) |\r\n| **Models** | [Basic Models](../03-models/basic-models.lotnb) \\| [Action Models](../03-models/action-models.lotnb) \\| [Inheritance](../03-models/model-inheritance.lotnb) |\r\n| **Routes** | [MQTT Bridge](../04-routes/mqtt-bridge.lotnb) \\| [Database](../04-routes/database-routes.lotnb) |\r\n| **Python** | [Simple](../05-python/simple-python.lotnb) \\| [Advanced](../05-python/advanced-python.lotnb) |\r\n\r\n</details>\r\n\r\n---\r\n\r\n> **CAUTION - Free Tier Resource Limits**\r\n>\r\n> The free version of Coreflux has resource limits:\r\n> - **Routes**: 2 maximum\r\n> - **Actions**: 12 maximum\r\n> - **Models**: 40 maximum\r\n>\r\n> Delete unused resources before creating new ones during exercises.\r\n\r\n---\r\n\r\n## Learning Objectives\r\n\r\nIn this tutorial, you will learn:\r\n- IF/ELSE statement syntax and logic\r\n- Comparison operators (=, >, <, >=, <=, !=)\r\n- Complex conditional chains with multiple conditions\r\n- Counter logic with state persistence\r\n- Boolean logic and text matching\r\n- Building intelligent automation systems\r\n\r\n---\r\n\r\n## 📖 Introduction\r\n\r\n**Conditional Logic** is what makes LoT truly intelligent. It enables:\r\n- Smart decision making based on data\r\n- Automated responses to different conditions\r\n- Complex business logic implementation\r\n- Threshold-based monitoring and alerts\r\n\r\n### Real-World Applications\r\n- **Quality Control**: Reject products outside specifications\r\n- **Safety Systems**: Shut down equipment when limits exceeded\r\n- **Process Optimization**: Adjust parameters based on conditions\r\n- **Predictive Maintenance**: Alert when patterns indicate issues\r\n\r\n---\r\n\r\n## 🧠 Core Concepts\r\n\r\n### IF/ELSE Syntax\r\n\r\n```lot\r\nIF condition THEN\r\n // Actions when condition is true\r\nELSE\r\n // Actions when condition is false\r\n```\r\n\r\n### Comparison Operators\r\n\r\n- `=` or `EQUALS` - Equal to\r\n- `>` - Greater than\r\n- `<` - Less than\r\n- `>=` - Greater than or equal\r\n- `<=` - Less than or equal\r\n- `!=` or `NOT EQUALS` - Not equal to\r\n\r\n### Text Operations\r\n\r\n- `CONTAINS \"text\"` - Check if payload contains text\r\n- `EQUALS \"text\"` - Exact text match\r\n- String concatenation with `+`\r\n\r\n### Boolean Logic\r\n\r\n- `AND` - Both conditions must be true\r\n- `OR` - Either condition can be true\r\n- `NOT` - Inverts the condition\r\n\r\n---\r\n\r\n## 🛠️ Hands-On Examples\r\n\r\n### Example 1: Simple Temperature Monitor\r\n\r\nLet's create a basic temperature monitoring system:"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION TemperatureMonitor\r\nON TOPIC \"sensors/+/temperature\" DO\r\n SET \"sensor_id\" WITH TOPIC POSITION 2\r\n \r\n // Check temperature ranges\r\n IF PAYLOAD > 80 THEN\r\n PUBLISH TOPIC \"alarms/temperature/\" + {sensor_id} WITH \"HIGH - Temperature: \" + PAYLOAD + \"°C\"\r\n PUBLISH TOPIC \"alarms/temperature/\" + {sensor_id} + \"/level\" WITH \"HIGH\"\r\n ELSE IF PAYLOAD > 60 THEN\r\n PUBLISH TOPIC \"status/temperature/\" + {sensor_id} WITH \"NORMAL - Temperature: \" + PAYLOAD + \"°C\"\r\n PUBLISH TOPIC \"status/temperature/\" + {sensor_id} + \"/level\" WITH \"NORMAL\"\r\n ELSE\r\n PUBLISH TOPIC \"status/temperature/\" + {sensor_id} WITH \"LOW - Temperature: \" + PAYLOAD + \"°C\"\r\n PUBLISH TOPIC \"status/temperature/\" + {sensor_id} + \"/level\" WITH \"LOW\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Monitors temperature readings from any sensor\r\n- Classifies temperatures into HIGH (>80°C), NORMAL (60-80°C), LOW (<60°C)\r\n- Routes messages to different topics based on severity\r\n- Provides both descriptive messages and simple level indicators\r\n- Demonstrates multi-level conditional logic\r\n\r\n**Test it:**\r\n```\r\nPublish to: sensors/temp001/temperature\r\nPayload: 85\r\nResults:\r\n alarms/temperature/temp001: \"HIGH - Temperature: 85°C\"\r\n alarms/temperature/temp001/level: \"HIGH\"\r\n```\r\n\r\n---\r\n\r\n### Example 2: Smart Counter with Limits \r\n\r\nLet's build an intelligent counter system:"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION SmartCounter\r\nON TOPIC \"counter/+/increment\" DO\r\n SET \"counter_id\" WITH TOPIC POSITION 2\r\n SET \"current_value\" WITH (GET TOPIC \"counters/\" + {counter_id} + \"/value\" AS INT)\r\n PUBLISH TOPIC \"teste\" WITH {current_value}\r\n SET \"increment_amount\" WITH PAYLOAD\r\n SET \"new_value\" WITH ({current_value} + {increment_amount})\r\n \r\n // Check counter limits\r\n IF {new_value} > 1000 THEN\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/error\" WITH \"Counter overflow! Attempted value: \" + {new_value}\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/status\" WITH \"ERROR\"\r\n ELSE IF {new_value} < 0 THEN\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/error\" WITH \"Counter underflow! Attempted value: \" + {new_value}\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/status\" WITH \"ERROR\"\r\n ELSE\r\n // Valid increment\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/value\" WITH {new_value}\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/last_increment\" WITH {increment_amount}\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/last_update\" WITH TIMESTAMP \"UTC\"\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/status\" WITH \"OK\"\r\n \r\n // Milestone notifications\r\n IF {new_value} = 100 THEN\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/milestone\" WITH \"Reached 100!\"\r\n ELSE IF {new_value} = 500 THEN\r\n PUBLISH TOPIC \"counters/\" + {counter_id} + \"/milestone\" WITH \"Reached 500!\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Accepts increment commands for any counter\r\n- Validates new values against limits (0-1000)\r\n- Prevents overflow and underflow conditions\r\n- Tracks increment history and timestamps\r\n- Provides milestone notifications\r\n- Demonstrates complex validation logic\r\n\r\n**Test it:**\r\n```\r\nPublish to: counter/production001/increment\r\nPayload: 10\r\nResults:\r\n counters/production001/value: 10\r\n counters/production001/last_increment: 10\r\n counters/production001/status: \"OK\"\r\n```\r\n\r\n---\r\n\r\n### Example 3: Production Line Controller \r\n\r\nLet's create a production line control system:"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION ProductionLineController\r\nON TOPIC \"production/+/command\" DO\r\n SET \"line_id\" WITH TOPIC POSITION 2\r\n SET \"current_status\" WITH GET TOPIC \"production/\" + {line_id} + \"/status\"\r\n \r\n // Process different commands\r\n IF PAYLOAD EQUALS \"START\" THEN\r\n IF {current_status} EQUALS \"STOPPED\" OR {current_status} EQUALS EMPTY THEN\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/status\" WITH \"STARTING\"\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/start_time\" WITH TIMESTAMP \"UNIX\"\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/parts_produced\" WITH 0\r\n PUBLISH TOPIC \"logs/production/\" + {line_id} WITH \"Line started at \" + TIMESTAMP \"UTC\"\r\n ELSE\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/error\" WITH \"Cannot start - Line is \" + {current_status}\r\n \r\n ELSE IF PAYLOAD EQUALS \"STOP\" THEN\r\n IF {current_status} EQUALS \"RUNNING\" OR {current_status} EQUALS \"STARTING\" THEN\r\n SET \"runtime\" WITH (TIMESTAMP \"UNIX\" - GET TOPIC \"production/\" + {line_id} + \"/start_time\" AS DOUBLE)\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/status\" WITH \"STOPPED\"\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/total_runtime\" WITH {runtime}\r\n PUBLISH TOPIC \"logs/production/\" + {line_id} WITH \"Line stopped after \" + {runtime} + \" seconds\"\r\n ELSE\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/error\" WITH \"Cannot stop - Line is \" + {current_status}\r\n \r\n ELSE IF PAYLOAD EQUALS \"RESET\" THEN\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/status\" WITH \"STOPPED\"\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/parts_produced\" WITH 0\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/total_runtime\" WITH 0\r\n PUBLISH TOPIC \"logs/production/\" + {line_id} WITH \"Line reset at \" + TIMESTAMP \"UTC\"\r\n \r\n ELSE\r\n PUBLISH TOPIC \"production/\" + {line_id} + \"/error\" WITH \"Unknown command: \" + PAYLOAD"
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\n- Processes START, STOP, and RESET commands for production lines\n- Validates commands against current line status\n- Tracks start times and calculates runtime\n- Maintains production counters and logs\n- Prevents invalid state transitions\n- Demonstrates complex state machine logic\n\n**Test it:**\n```\nPublish to: production/line001/command\nPayload: \"START\"\nResults:\n production/line001/status: \"STARTING\"\n production/line001/start_time: 1729864215\n production/line001/parts_produced: 0\n logs/production/line001: \"Line started at 2025-10-25T14:30:15Z\"\n```\n\n---\n\n### Example 4: Quality Control System - Progressive Build-Up\n\nLet's build a quality control system step by step to understand each component:\n\n#### Step 1: Basic Quality Check (Single Threshold)"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION QualityStep1_BasicCheck\r\nON TOPIC \"quality/step1/+/measurement\" DO\r\n SET \"station_id\" WITH TOPIC POSITION 3\r\n SET \"measurement_value\" WITH PAYLOAD\r\n \r\n // Single threshold check\r\n IF {measurement_value} > 21.5 THEN\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"REJECT\"\r\n ELSE\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"OK\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Very simple: Just checks if measurement is too high\r\n- Only two outcomes: REJECT or OK\r\n- No counters, no complex logic\r\n\r\n**Test it:**\r\n```\r\nPublish to: quality/step1/station001/measurement\r\nPayload: 22.0\r\nResult: quality/station001/result: \"REJECT\"\r\n\r\nPublish to: quality/step1/station001/measurement \r\nPayload: 20.0\r\nResult: quality/station001/result: \"OK\"\r\n```\r\n\r\n---\r\n\r\n#### Step 2: Two-Way Quality Check (Upper AND Lower Bounds)"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION QualityStep2_TwoWayCheck\r\nON TOPIC \"quality/step2/+/measurement\" DO\r\n SET \"station_id\" WITH TOPIC POSITION 3\r\n SET \"measurement_value\" WITH PAYLOAD\r\n SET \"min_acceptable\" WITH 18.5\r\n SET \"max_acceptable\" WITH 21.5\r\n \r\n // Check both upper and lower bounds\r\n IF {measurement_value} < {min_acceptable} OR {measurement_value} > {max_acceptable} THEN\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"REJECT\"\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reason\" WITH \"Out of spec: \" + {measurement_value}\r\n ELSE\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"OK\"\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reason\" WITH \"In spec: \" + {measurement_value}"
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Checks both upper AND lower limits using OR\r\n- Uses variables for thresholds\r\n- Provides reason messages\r\n- Still no counters\r\n\r\n**Test it:**\r\n```\r\nPublish to: quality/step2/station001/measurement\r\nPayload: 17.0 → REJECT (too low)\r\nPayload: 22.0 → REJECT (too high) \r\nPayload: 20.0 → OK (in range)\r\n```\r\n\r\n---\r\n\r\n#### Step 3: Three-Tier Quality System (No Counters)"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION QualityStep3_ThreeTier\r\nON TOPIC \"quality/step3/+/measurement\" DO\r\n SET \"station_id\" WITH TOPIC POSITION 3\r\n SET \"measurement_value\" WITH PAYLOAD\r\n SET \"min_acceptable\" WITH 18.5\r\n SET \"max_acceptable\" WITH 21.5\r\n SET \"min_optimal\" WITH 19.0\r\n SET \"max_optimal\" WITH 21.0\r\n \r\n // Three-tier classification\r\n IF {measurement_value} < {min_acceptable} OR {measurement_value} > {max_acceptable} THEN\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"REJECT\"\r\n ELSE IF {measurement_value} >= {min_optimal} AND {measurement_value} <= {max_optimal} THEN\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"OPTIMAL\"\r\n ELSE\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"ACCEPTABLE\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Three quality levels: REJECT, ACCEPTABLE, OPTIMAL\r\n- Uses ELSE IF for multiple conditions\r\n- Still no counters - just classification\r\n\r\n**Quality Ranges:**\r\n- REJECT: < 18.5 or > 21.5\r\n- OPTIMAL: 19.0 to 21.0\r\n- ACCEPTABLE: Everything else (18.5-19.0 or 21.0-21.5)\r\n\r\n**Test it:**\r\n```\r\nPublish to: quality/step3/station001/measurement\r\nPayload: 17.0 → REJECT\r\nPayload: 18.7 → ACCEPTABLE\r\nPayload: 20.0 → OPTIMAL\r\nPayload: 21.2 → ACCEPTABLE\r\nPayload: 22.0 → REJECT\r\n```\r\n\r\n---\r\n\r\n#### Step 4: Add Simple Counter (One Category)"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION QualityStep4_WithOneCounter\r\nON TOPIC \"quality/step4/+/measurement\" DO\r\n SET \"station_id\" WITH TOPIC POSITION 3\r\n SET \"measurement_value\" WITH PAYLOAD\r\n SET \"max_acceptable\" WITH 21.5\r\n \r\n IF {measurement_value} > {max_acceptable} THEN\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"REJECT\"\r\n \r\n // Add counter for rejects\r\n SET \"reject_count\" WITH (GET TOPIC \"quality/\" + {station_id} + \"/reject_count\" AS INT) + 1\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reject_count\" WITH {reject_count}\r\n ELSE\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"OK\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\r\n- Adds a counter that tracks REJECT count\r\n- Uses GET TOPIC with AS INT to read current count\r\n- Adds 1 and publishes back\r\n- Counter persists across measurements\r\n\r\n**Test it:**\r\n```\r\nPublish to: quality/step4/station001/measurement\r\nPayload: 22.0 → reject_count = 1\r\nPayload: 23.0 → reject_count = 2\r\nPayload: 20.0 → OK (counter unchanged)\r\nPayload: 24.0 → reject_count = 3\r\n```\r\n\r\n---\r\n\r\n#### Step 5: Complete Quality Control System (All Features)"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION QualityControlSystem\r\nON TOPIC \"quality/+/measurement\" DO\r\n SET \"station_id\" WITH TOPIC POSITION 2\r\n SET \"measurement_value\" WITH PAYLOAD\r\n \r\n // Quality thresholds\r\n SET \"min_acceptable\" WITH 18.5\r\n SET \"max_acceptable\" WITH 21.5\r\n SET \"min_optimal\" WITH 19.0\r\n SET \"max_optimal\" WITH 21.0\r\n \r\n // Determine quality level\r\n IF {measurement_value} < {min_acceptable} OR {measurement_value} > {max_acceptable} THEN\r\n // Reject - outside acceptable range\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"REJECT\"\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reason\" WITH \"Out of specification: \" + {measurement_value}\r\n PUBLISH TOPIC \"alarms/quality/\" + {station_id} WITH \"REJECT - Value: \" + {measurement_value}\r\n \r\n // Update reject counter\r\n SET \"reject_count\" WITH ((GET TOPIC \"quality/\" + {station_id} + \"/reject_count\") + 1)\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reject_count\" WITH {reject_count}\r\n \r\n ELSE IF {measurement_value} >= {min_optimal} AND {measurement_value} <= {max_optimal} THEN\r\n // Optimal quality\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"OPTIMAL\"\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reason\" WITH \"Within optimal range: \" + {measurement_value}\r\n \r\n // Update optimal counter\r\n SET \"optimal_count\" WITH ((GET TOPIC \"quality/\" + {station_id} + \"/optimal_count\") + 1)\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/optimal_count\" WITH {optimal_count}\r\n \r\n ELSE\r\n // Acceptable but not optimal\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/result\" WITH \"ACCEPTABLE\"\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/reason\" WITH \"Acceptable range: \" + {measurement_value}\r\n \r\n // Update acceptable counter\r\n SET \"acceptable_count\" WITH ((GET TOPIC \"quality/\" + {station_id} + \"/acceptable_count\") + 1)\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/acceptable_count\" WITH {acceptable_count}\r\n \r\n // Always update total count and timestamp\r\n SET \"total_count\" WITH ((GET TOPIC \"quality/\" + {station_id} + \"/total_count\") + 1)\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/total_count\" WITH {total_count}\r\n PUBLISH TOPIC \"quality/\" + {station_id} + \"/last_measurement\" WITH TIMESTAMP \"UTC\""
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\n- Implements a 3-tier quality control system (REJECT/ACCEPTABLE/OPTIMAL)\n- Uses multiple comparison operators and boolean logic\n- Maintains separate counters for each quality level\n- Provides detailed reasoning for each decision\n- Generates alarms for rejected items\n- Demonstrates complex multi-condition logic\n\n**Quality Ranges:**\n- **REJECT**: < 18.5 or > 21.5\n- **ACCEPTABLE**: 18.5-19.0 or 21.0-21.5\n- **OPTIMAL**: 19.0-21.0\n\n**Test it:**\n```\nPublish to: quality/station001/measurement\nPayload: 19.5\nResults:\n quality/station001/result: \"OPTIMAL\"\n quality/station001/reason: \"Within optimal range: 19.5\"\n quality/station001/optimal_count: 1\n quality/station001/total_count: 1\n```\n\n**This is the complete system** with all the features from Steps 1-4 combined.\n\n---\n\n### Example 5: Advanced Counter with Multiple Conditions\n\nLet's create a sophisticated counting system:"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION AdvancedCounterSystem\r\nON TOPIC \"machines/+/button\" DO\r\n SET \"machine_id\" WITH TOPIC POSITION 2\r\n \r\n // Only process button press (true), ignore button release (false)\r\n IF PAYLOAD EQUALS TRUE THEN\r\n // Get current counters\r\n SET \"current_count\" WITH GET TOPIC \"machines/\" + {machine_id} + \"/count\"\r\n SET \"daily_count\" WITH GET TOPIC \"machines/\" + {machine_id} + \"/daily_count\"\r\n SET \"total_count\" WITH GET TOPIC \"machines/\" + {machine_id} + \"/total_count\"\r\n \r\n // Increment all counters\r\n SET \"new_count\" WITH ({current_count} + 1)\r\n SET \"new_daily\" WITH ({daily_count} + 1)\r\n SET \"new_total\" WITH ({total_count} + 1)\r\n \r\n // Check for counter limits and special conditions\r\n IF {new_count} > 25 THEN\r\n // Reset current counter and trigger maintenance\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/count\" WITH 0\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/maintenance\" WITH \"Counter limit reached - Maintenance required\"\r\n PUBLISH TOPIC \"alarms/maintenance/\" + {machine_id} WITH \"Cycle limit reached after 25 operations\"\r\n ELSE\r\n // Normal increment\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/count\" WITH {new_count}\r\n \r\n // Always update daily and total counters\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/daily_count\" WITH {new_daily}\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/total_count\" WITH {new_total}\r\n \r\n // Milestone notifications\r\n IF {new_daily} = 100 THEN\r\n PUBLISH TOPIC \"achievements/\" + {machine_id} WITH \"Daily milestone: 100 operations completed!\"\r\n ELSE IF {new_total} = 1000 THEN\r\n PUBLISH TOPIC \"achievements/\" + {machine_id} WITH \"Total milestone: 1000 operations completed!\"\r\n \r\n // Update status\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/last_operation\" WITH TIMESTAMP \"UTC\"\r\n PUBLISH TOPIC \"machines/\" + {machine_id} + \"/status\" WITH \"Active - Count: \" + {new_count}"
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\n- Processes button press events (ignores button release)\n- Maintains three different counters: current, daily, and total\n- Implements automatic reset at 25 operations\n- Triggers maintenance alerts when limits reached\n- Provides milestone achievements at 100 and 1000 operations\n- Updates machine status and timestamps\n- Demonstrates complex counter management\n\n**Test it:**\n```\nPublish to: machines/press001/button\nPayload: true\nResults:\n machines/press001/count: 1\n machines/press001/daily_count: 1\n machines/press001/total_count: 1\n machines/press001/status: \"Active - Count: 1\"\n```\n\n---\n\n### Example 6: Text-Based Command Processor\n\nLet's process text commands with conditional logic:"
},
{
"kind": 2,
"language": "lot",
"value": "DEFINE ACTION TextCommandProcessor\r\nON TOPIC \"commands/+/text\" DO\r\n SET \"device_id\" WITH TOPIC POSITION 2\r\n \r\n // Process different command types\r\n IF PAYLOAD CONTAINS \"start\" THEN\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/action\" WITH \"STARTING\"\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/command_log\" WITH \"Start command received at \" + TIMESTAMP \"UTC\"\r\n \r\n ELSE IF PAYLOAD CONTAINS \"stop\" THEN\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/action\" WITH \"STOPPING\"\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/command_log\" WITH \"Stop command received at \" + TIMESTAMP \"UTC\"\r\n \r\n ELSE IF PAYLOAD CONTAINS \"status\" THEN\r\n SET \"current_status\" WITH GET TOPIC \"devices/\" + {device_id} + \"/status\"\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/response\" WITH \"Current status: \" + {current_status}\r\n \r\n ELSE IF PAYLOAD CONTAINS \"reset\" THEN\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/action\" WITH \"RESETTING\"\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/counter\" WITH 0\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/error_count\" WITH 0\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/command_log\" WITH \"Reset command received at \" + TIMESTAMP \"UTC\"\r\n \r\n ELSE IF PAYLOAD CONTAINS \"emergency\" THEN\r\n // Emergency stop - highest priority\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/action\" WITH \"EMERGENCY_STOP\"\r\n PUBLISH TOPIC \"alarms/emergency/\" + {device_id} WITH \"Emergency stop activated: \" + PAYLOAD\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/command_log\" WITH \"EMERGENCY: \" + PAYLOAD + \" at \" + TIMESTAMP \"UTC\"\r\n \r\n ELSE\r\n // Unknown command\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/error\" WITH \"Unknown command: \" + PAYLOAD\r\n SET \"error_count\" WITH ((GET TOPIC \"devices/\" + {device_id} + \"/error_count\") + 1)\r\n PUBLISH TOPIC \"devices/\" + {device_id} + \"/error_count\" WITH {error_count}"
},
{
"kind": 1,
"language": "markdown",
"value": "**What this does:**\n- Processes natural language commands using `CONTAINS`\n- Handles multiple command types: start, stop, status, reset, emergency\n- Maintains command logs with timestamps\n- Implements emergency stop with high priority routing\n- Tracks unknown commands and error counts\n- Demonstrates text processing and command routing\n\n**Test it:**\n```\nPublish to: commands/pump001/text\nPayload: \"please start the pump\"\nResults:\n devices/pump001/action: \"STARTING\"\n devices/pump001/command_log: \"Start command received at 2025-10-25T14:30:15Z\"\n```\n\n---\n\n## 🏋️ Exercises\n\n### Exercise 1: Simple Threshold Monitor\n**Task**: Create an action that monitors `sensors/+/pressure` and:\n- If pressure > 50: publish \"HIGH\" to `alerts/pressure/SENSOR_ID`\n- If pressure < 10: publish \"LOW\" to `alerts/pressure/SENSOR_ID`\n- Otherwise: publish \"NORMAL\" to `status/pressure/SENSOR_ID`"
},
{
"kind": 2,
"language": "lot",
"value": "// Exercise 1: Write your solution here\n"
},
{
"kind": 1,
"language": "markdown",
"value": "### Exercise 2: Smart Light Controller\n**Task**: Create an action that processes `lights/+/command` and:\n- If payload is \"on\": set light status to \"ON\" and increment on_count\n- If payload is \"off\": set light status to \"OFF\" and increment off_count\n- If payload is \"toggle\": switch between ON/OFF based on current status\n- Track total_operations count"
},
{
"kind": 2,
"language": "lot",
"value": "// Exercise 2: Write your solution here\n"
},
{
"kind": 1,
"language": "markdown",
"value": "### Exercise 3: Production Efficiency Calculator\n**Task**: Create an action that monitors `production/+/completed` and:\n- Tracks parts completed per hour\n- If rate > 100 parts/hour: status = \"EXCELLENT\"\n- If rate > 75 parts/hour: status = \"GOOD\"\n- If rate > 50 parts/hour: status = \"ACCEPTABLE\"\n- If rate <= 50 parts/hour: status = \"POOR\" and create alarm\n\n**Challenge**: Use timestamps to calculate actual hourly rates."
},
{
"kind": 2,
"language": "lot",
"value": "// Exercise 3: Write your solution here\n"
},
{
"kind": 1,
"language": "markdown",
"value": "### Exercise 4: Multi-Condition Alarm System\n**Task**: Create an action that processes `sensors/+/+/reading` (sensor_type/sensor_id/reading) and:\n- For temperature sensors: alarm if > 80°C or < 5°C\n- For pressure sensors: alarm if > 100 PSI or < 5 PSI\n- For vibration sensors: alarm if > 10 mm/s\n- Route alarms to `alarms/SENSOR_TYPE/SENSOR_ID`\n- Include sensor context in alarm messages"
},
{
"kind": 2,
"language": "lot",
"value": "// Exercise 4: Write your solution here\n"
},
{
"kind": 1,
"language": "markdown",
"value": "\n\n---\n\n## 🎯 Checkpoint Questions\n\n1. **What's the difference between `=` and `CONTAINS`?**\n - Answer: `=` checks exact equality, `CONTAINS` checks if text is present anywhere in the payload\n\n2. **How do you chain multiple conditions?**\n - Answer: Use `ELSE IF` for additional conditions, `AND`/`OR` for compound conditions\n\n3. **What happens if you don't provide an `ELSE` clause?**\n - Answer: If no conditions match, no actions are executed\n\n4. **How do you check if a topic is empty or doesn't exist?**\n - Answer: Use `EQUALS EMPTY` or compare against default values\n\n---\n\n## 📝 Summary\n\n### Key Concepts Learned\n✅ **IF/ELSE Logic** - Conditional execution based on data \n✅ **Comparison Operators** - =, >, <, >=, <=, != \n✅ **Boolean Logic** - AND, OR, NOT combinations \n✅ **Text Operations** - CONTAINS, EQUALS for string processing \n✅ **State Management** - Persistent counters and status tracking \n✅ **Complex Conditions** - Multi-level decision trees \n\n### Logic Patterns Mastered\n- **Threshold Monitoring** - Comparing values against limits\n- **State Machines** - Managing device states and transitions\n- **Counter Management** - Increment, reset, and limit handling\n- **Command Processing** - Text-based command interpretation\n- **Quality Control** - Multi-criteria decision making\n\n### Next Steps\n- Practice building complex conditional logic\n- Experiment with different comparison operators\n- Try combining conditions with AND/OR\n- Move on to [Basic Models](../03-models/basic-models.lotnb) to learn data structures\n\n---\n\n## 🚀 Further Exploration\n\n### Advanced Logic Patterns\n- Nested IF statements for complex decision trees\n- Time-based conditions (business hours, weekends)\n- Statistical thresholds (moving averages, standard deviations)\n\n### Performance Considerations\n- Optimize condition order (most likely conditions first)\n- Minimize topic reads in complex conditions\n- Use variables to avoid repeated calculations\n\n### Real-World Projects\n- Build complete quality control systems\n- Create intelligent alarm management\n- Implement automated process control\n\n---\n\n**Ready to structure your data? Continue with [🏗️ Basic Models](../03-models/basic-models.lotnb)!**\n\n[⬅️ Previous: Topic Actions](../01-basics/topic-actions.lotnb) | [🏠 Back to Index](../index.lotnb) | [➡️ Next: Basic Models](../03-models/basic-models.lotnb)"
}
]