Respons Automatik terhadap Peristiwa Sensor
Jika suhu > ambang → amaran → gerakkan: gelung kawalan IoT dipacu ejen.
Respons Automatik terhadap Peristiwa Sensor ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Tindak Balas Ejen Dipacu Peristiwa Automatik
Apabila sensor melepasi ambang, ejen mesti bertindak secara automatik tanpa campur tangan manusia. Cabaran utama ialah menentukan tindakan yang perlu diambil, memastikan peristiwa yang sama tidak mencetuskan tindakan pendua dan mematuhi tempoh bertenang supaya ejen tidak membanjiri penggerak dengan arahan.
Menentukan Polisi Tindakan
Polisi tindakan memetakan keadaan sensor kepada tindak balas ejen. Tentukan polisi secara deklaratif supaya polisi mudah dibaca dan diubah suai tanpa menyentuh kod logik. Setiap polisi mempunyai syarat, keutamaan dan satu atau lebih tindakan.
ACTION_POLICIES = [
{
'name': 'HIGH_TEMP_ALERT',
'topic': 'sensors/temperature',
'condition': lambda v: v > 38,
'priority': 'critical',
'actions': ['TURN_ON_COOLING', 'ALERT_MAINTENANCE', 'LOG_EVENT']
},
{
'name': 'HIGH_TEMP_WARNING',
'topic': 'sensors/temperature',
'condition': lambda v: 35 < v <= 38,
'priority': 'warning',
'actions': ['ALERT_MAINTENANCE', 'LOG_EVENT']
},
{
'name': 'LOW_HUMIDITY',
'topic': 'sensors/humidity',
'condition': lambda v: v < 30,
'priority': 'warning',
'actions': ['TURN_ON_HUMIDIFIER', 'LOG_EVENT']
}
]
def match_policies(topic: str, value: float) -> list:
return [
p for p in ACTION_POLICIES
if p['topic'] == topic and p['condition'](value)
]
if __name__ == '__main__':
matches = match_policies('sensors/temperature', 39)
print('Matched policies for temperature=39:')
for p in matches:
print(f" {p['name']} ({p['priority']}): {p['actions']}")
Baris Gilir Tindakan
Baris gilir tindakan memisahkan pengesanan peristiwa daripada pelaksanaan tindakan. Peristiwa dimasukkan ke dalam baris gilir; pekerja mengeluarkan dan melaksanakannya. Ini menghalang gelung penerimaan MQTT daripada tersekat dan membolehkan percubaan semula jika tindakan gagal.
import queue
import threading
from datetime import datetime
action_queue: queue.Queue = queue.Queue(maxsize=500)
def enqueue_action(action_name: str, context: dict, priority: str = 'normal'):
item = {
'action': action_name,
'context': context,
'priority': priority,
'enqueued_at': datetime.utcnow().isoformat()
}
try:
action_queue.put_nowait(item)
print(f'Enqueued: {action_name}')
except queue.Full:
print(f'WARNING: Action queue full, dropping {action_name}')
def action_worker(executor_fn):
"""Run in a background thread, executing actions from the queue."""
while True:
item = action_queue.get()
try:
executor_fn(item['action'], item['context'])
except Exception as e:
print(f'Action failed: {item["action"]} — {e}')
finally:
action_queue.task_done()
# Start worker thread:
# worker_thread = threading.Thread(target=action_worker, args=(execute_action,), daemon=True)
# worker_thread.start()
if __name__ == '__main__':
enqueue_action('TURN_ON_COOLING', {'zone': 'server-room'}, priority='critical')
enqueue_action('LOG_EVENT', {'msg': 'temperature nominal'})
print('Queue size:', action_queue.qsize())
Penyahduplikatan Peristiwa
Tanpa penyahduplikatan, suhu yang kekal melebihi 38°C selama 10 minit pada kadar 1 bacaan/saat menghasilkan 600 peristiwa yang serupa. Penyahduplikatan memastikan gabungan (topik, syarat, tindakan) yang sama hanya dicetuskan sekali bagi setiap peristiwa dan ditetapkan semula apabila syarat tidak lagi dipenuhi.
class EventDeduplicator:
def __init__(self):
# active_events: (topic, policy_name) -> event_start_time
self._active: dict = {}
def is_new_event(self, topic: str, policy_name: str) -> bool:
key = (topic, policy_name)
return key not in self._active
def mark_active(self, topic: str, policy_name: str):
self._active[(topic, policy_name)] = datetime.utcnow()
def clear_event(self, topic: str, policy_name: str):
key = (topic, policy_name)
if key in self._active:
duration = (datetime.utcnow() - self._active.pop(key)).seconds
print(f'Event cleared: {policy_name} (lasted {duration}s)')
def clear_topic_if_normal(
self, topic: str, value: float, normal_fn
):
if normal_fn(value):
keys = [k for k in self._active if k[0] == topic]
for k in keys:
self.clear_event(k[0], k[1])
dedup = EventDeduplicator()
dedup.mark_active('sensors/temperature', 'HIGH_TEMP_ALERT')
print('New event?', dedup.is_new_event('sensors/temperature', 'HIGH_TEMP_ALERT'))Tempoh Bertenang
Walaupun selepas sesuatu peristiwa berhenti dan tercetus semula, tempoh bertenang menghalang pencetusan semula yang terlalu pantas. Gabungkan penyahduplikatan (dicetuskan sekali selagi syarat dipenuhi) dengan tempoh bertenang (tunggu N minit selepas syarat tidak lagi dipenuhi sebelum membenarkan amaran yang sama dicetuskan semula).
from datetime import datetime, timedelta
class CoolDownManager:
def __init__(self, cool_down_minutes: int = 15):
self.cool_down = timedelta(minutes=cool_down_minutes)
self._cleared_at: dict = {} # (topic, policy) -> cleared_datetime
def is_in_cool_down(self, topic: str, policy_name: str) -> bool:
key = (topic, policy_name)
cleared_at = self._cleared_at.get(key)
if cleared_at is None:
return False
return datetime.utcnow() - cleared_at < self.cool_down
def record_clear(self, topic: str, policy_name: str):
self._cleared_at[(topic, policy_name)] = datetime.utcnow()
def time_remaining(self, topic: str, policy_name: str) -> int:
key = (topic, policy_name)
cleared_at = self._cleared_at.get(key)
if cleared_at is None:
return 0
elapsed = datetime.utcnow() - cleared_at
remaining = self.cool_down - elapsed
return max(0, int(remaining.total_seconds()))
cooldown = CoolDownManager(cool_down_minutes=15)
cooldown.record_clear('sensors/temperature', 'HIGH_TEMP_ALERT')
print('In cool-down?', cooldown.is_in_cool_down('sensors/temperature', 'HIGH_TEMP_ALERT'))Keputusan Tindakan Berbantukan LLM
Untuk situasi kompleks — berbilang amaran serentak, polisi yang bercanggah atau gabungan bacaan yang luar biasa — serahkan keputusan kepada LLM. LLM menerima konteks sensor lengkap dan mencadangkan pelan tindakan mengikut keutamaan.
import anthropic
import json
def llm_decide_actions(
sensor_readings: dict,
active_policies: list
) -> list:
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
context = json.dumps({
'readings': sensor_readings,
'triggered_policies': [p['name'] for p in active_policies]
}, indent=2)
prompt = (
f'Current sensor state:\n{context}\n\n'
'Multiple alert policies are active. '
'Recommend an ordered list of actions to take. '
'Consider conflicting effects (e.g., humidifier and cooling may conflict).\n'
'Return JSON: {"recommended_actions": [str], "reasoning": str}'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': prompt}]
)
return json.loads(response.content[0].text)Melaksanakan Tindakan melalui MQTT
Tindakan dilaksanakan dengan menerbitkan mesej arahan kepada topik MQTT khusus peranti. Muatan arahan mengikut skema standard: nama tindakan, parameter, ID permintaan untuk pengesahan dan TTL (arahan tamat tempoh jika peranti berada di luar talian terlalu lama).
import json
import uuid
from datetime import datetime, timedelta
ACTION_TOPICS = {
'TURN_ON_COOLING': 'devices/hvac/commands',
'TURN_OFF_COOLING': 'devices/hvac/commands',
'TURN_ON_HUMIDIFIER': 'devices/humidifier/commands',
'ALERT_MAINTENANCE': 'notifications/maintenance',
'LOG_EVENT': 'logs/agent_events'
}
def execute_action(action_name: str, context: dict, mqtt_client) -> str:
topic = ACTION_TOPICS.get(action_name)
if not topic:
print(f'No topic defined for action: {action_name}')
return 'unknown_action'
request_id = str(uuid.uuid4())[:8]
ttl = (datetime.utcnow() + timedelta(minutes=5)).isoformat()
payload = json.dumps({
'action': action_name,
'request_id': request_id,
'context': context,
'ttl': ttl
})
mqtt_client.publish(topic, payload, qos=1)
print(f'Executed {action_name} -> {topic} (req={request_id})')
return request_id
if __name__ == '__main__':
class FakeMQTT:
def publish(self, topic, payload, qos=1):
pass
execute_action('TURN_ON_COOLING', {'zone': 'server-room'}, FakeMQTT())
Pengesahan Tindakan
Peranti hendaklah mengesahkan arahan yang diterima dengan menerbitkan mesej kepada topik pengesahan. Ejen melanggan topik pengesahan dan boleh mencuba semula jika tiada pengesahan diterima dalam tempoh tamat masa.
import threading
from collections import defaultdict
class AckTracker:
def __init__(self, timeout_seconds: int = 30):
self.timeout = timeout_seconds
self._pending: dict = {} # request_id -> {'action', 'send_time', 'ack_event'}
def register(self, request_id: str, action_name: str):
event = threading.Event()
self._pending[request_id] = {
'action': action_name,
'send_time': datetime.utcnow(),
'ack_event': event
}
# Schedule timeout check
t = threading.Timer(self.timeout, self._on_timeout, args=[request_id])
t.daemon = True
t.start()
def acknowledge(self, request_id: str):
entry = self._pending.pop(request_id, None)
if entry:
entry['ack_event'].set()
print(f'Ack received for {entry["action"]} (req={request_id})')
def _on_timeout(self, request_id: str):
if request_id in self._pending:
action = self._pending.pop(request_id)['action']
print(f'TIMEOUT: No ack for {action} (req={request_id}) — retry?')Saluran Paip Peristiwa Sensor Lengkap
Menggabungkan semua komponen: penerimaan MQTT → padanan polisi → penyahduplikatan + pemeriksaan tempoh bertenang → masukkan tindakan ke baris gilir → pekerja melaksanakan melalui penerbitan MQTT → penjejakan pengesahan. Seni bina ini mengendalikan ribuan peristiwa sensor seminit tanpa tersekat.
class IoTAgentPipeline:
def __init__(self, mqtt_client):
self.mqtt = mqtt_client
self.dedup = EventDeduplicator()
self.cooldown = CoolDownManager(cool_down_minutes=15)
self.ack_tracker = AckTracker(timeout_seconds=30)
def on_sensor_message(self, topic: str, value: float):
policies = match_policies(topic, value)
self.dedup.clear_topic_if_normal(
topic, value,
normal_fn=lambda v: v <= 35 # below warning threshold
)
for policy in policies:
name = policy['name']
if not self.dedup.is_new_event(topic, name):
continue # already active, skip
if self.cooldown.is_in_cool_down(topic, name):
print(f'In cool-down: {name}')
continue
self.dedup.mark_active(topic, name)
ctx = {'topic': topic, 'value': value, 'policy': name}
for action in policy['actions']:
enqueue_action(action, ctx, policy['priority'])Laluan Eskalasi
Sesetengah situasi memerlukan eskalasi kepada manusia: kegagalan berulang untuk mengesahkan arahan, keadaan kritikal yang berterusan atau berbilang polisi yang bercanggah. Tentukan laluan eskalasi yang menghantar pemberitahuan tolak atau mencipta tiket.
import requests
def escalate_to_human(
reason: str,
sensor_data: dict,
webhook_url: str = 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
):
message = {
'text': (
f'*IoT Agent Escalation* \n'
f'Reason: {reason}\n'
f'Sensor data: {sensor_data}\n'
f'Time: {datetime.utcnow().isoformat()}'
)
}
try:
response = requests.post(webhook_url, json=message, timeout=5)
response.raise_for_status()
print(f'Escalation sent: {reason}')
except requests.RequestException as e:
print(f'Escalation failed: {e}')
# Fall back: log to file
with open('escalations.log', 'a') as f:
import json
f.write(json.dumps({'reason': reason, 'data': sensor_data}) + '\n')Menguji Saluran Paip Peristiwa
Sebelum menggunakan saluran paip peristiwa Anda dalam persekitaran pengeluaran, tulis ujian automatik yang mensimulasikan peristiwa sensor dan mengesahkan bahawa tindakan yang betul dimasukkan ke baris gilir. Uji setiap polisi secara berasingan, tingkah laku penyahduplikatan dan tamat tempoh bertenang.
import time
def test_high_temp_policy_fires_once():
dedup = EventDeduplicator()
cooldown = CoolDownManager(cool_down_minutes=0) # disable cooldown for test
pipeline = IoTAgentPipeline(None)
pipeline.dedup = dedup
pipeline.cooldown = cooldown
actions_fired = []
action_queue.queue.clear()
# Fire same event 5 times in a row
for _ in range(5):
pipeline.on_sensor_message('sensors/temperature', 40.0)
# Only 1 set of actions should have been enqueued
actions = list(action_queue.queue)
assert len(actions) > 0, 'At least one action should fire'
print(f'Actions enqueued: {len(actions)} (expected: just 1 event worth)')
return True
result = test_high_temp_policy_fires_once()
print('Test passed:', result)Semakan Pengetahuan
Apakah tujuan utama penyahduplikatan peristiwa dalam saluran paip peristiwa sensor?
Imbas Kembali: Tindak Balas Automatik terhadap Peristiwa Sensor
Cemerlang! Inilah perkara yang Anda pelajari:
- Polisi tindakan: pemetaan deklaratif syarat kepada tindakan dengan keutamaan
- Baris gilir tindakan: memisahkan pengesanan daripada pelaksanaan; utas pekerja memproses tindakan
- Penyahduplikatan: dicetuskan sekali bagi setiap peristiwa, bukan sekali bagi setiap bacaan
- Tempoh bertenang: menghalang pencetusan semula serta-merta selepas syarat tidak lagi dipenuhi
- Eskalasi LLM: situasi kompleks dengan berbilang polisi diserahkan kepada penaakulan LLM
- Penjejakan pengesahan: mengesan dan mencuba semula arahan yang tidak disahkan
Seterusnya: menggunakan ejen ringan pada peranti pinggir seperti Raspberry Pi.
Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Soalan Lazim
Adakah pelajaran “Respons Automatik terhadap Peristiwa Sensor” percuma?
Ya — teks penuh “Respons Automatik terhadap Peristiwa Sensor” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Respons Automatik terhadap Peristiwa Sensor”?
Jika suhu > ambang → amaran → gerakkan: gelung kawalan IoT dipacu ejen. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.
Berapa lamakah pelajaran “Respons Automatik terhadap Peristiwa Sensor” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?
Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Protokol MQTT untuk Integrasi Ejen
- Pemprosesan Data Siri Masa dalam Ejen
- Respons Automatik terhadap Peristiwa Sensor
- Pelaksanaan Ejen Ringan di Pinggir