news 2026/10/3 12:49:45

用霍尔传感器自娱自乐

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用霍尔传感器自娱自乐

猪咪闲来无事,创作"无中生有"阵。一边是一台可以播放声音的主机,一边是zero w绑着霍尔传感器。本来以为还要MQTT结果发现局域网里有更简单粗暴的实现方式,甚好。

zero端代码:

from gpiozero import DigitalInputDevice from signal import pause import time import json import urllib.request import logging import sys GPIO_PIN = 27 SERVER_URL = "http://192.168.50.2:5000/door/open" TOKEN = "your_shared_token_here" MIN_TRIGGER_INTERVAL = 1.0 last_trigger_ts = 0.0 LOG_FILE = "/home/pi/bug.txt" logging.basicConfig( filename=LOG_FILE, level=logging.ERROR, format="%(asctime)s [%(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) def handle_uncaught_exception(exc_type, exc_value, exc_traceback): logging.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_uncaught_exception sensor = DigitalInputDevice(GPIO_PIN, pull_up=True, bounce_time=0.05) def send_open_signal(): req = urllib.request.Request( SERVER_URL, data=json.dumps({"event": "door_open", "ts": time.time()}).encode("utf-8"), headers={ "Content-Type": "application/json", "X-Token": TOKEN }, method="POST", ) try: with urllib.request.urlopen(req, timeout=2): pass except Exception: logging.exception("Failed to send door_open signal") def on_inactive(): global last_trigger_ts now = time.time() if now - last_trigger_ts >= MIN_TRIGGER_INTERVAL: last_trigger_ts = now send_open_signal() sensor.when_deactivated = on_inactive pause()

4B主机端:

import json import os import subprocess import threading from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer # ===== 配置区 ===== HOST = "0.0.0.0" PORT = 5000 TOKEN = "your_shared_token_here" AUDIO_FILE = "/home/pi/aaa.m4a" # ffplay 参数:无窗口、播完退出、日志静默 FFPLAY_CMD = [ "ffplay", "-nodisp", "-autoexit", "-loglevel", "error", AUDIO_FILE ] lock = threading.Lock() current_proc = None def play_audio_once(): global current_proc with lock: # 若正在播放,就忽略新的触发,避免叠音 if current_proc is not None and current_proc.poll() is None: return False if not os.path.exists(AUDIO_FILE): print("音频文件不存在:", AUDIO_FILE) return False current_proc = subprocess.Popen(FFPLAY_CMD) return True class Handler(BaseHTTPRequestHandler): def do_POST(self): if self.path != "/door/open": self.send_response(404) self.end_headers() return token = self.headers.get("X-Token", "") if token != TOKEN: self.send_response(401) self.end_headers() self.wfile.write(b"unauthorized") return # 读 body(可选,不强依赖内容) length = int(self.headers.get("Content-Length", "0")) if length > 0: _ = self.rfile.read(length) ok = play_audio_once() self.send_response(200) self.end_headers() if ok: self.wfile.write(b"playing") #print("收到开门信号,开始播放") else: self.wfile.write(b"ignored_or_error") def log_message(self, format, *args): return def main(): server = ThreadingHTTPServer((HOST, PORT), Handler) print(f"Door receiver listening on {HOST}:{PORT}") server.serve_forever() if __name__ == "__main__": main()

接下来两台机器都做个开机自启,也就是各自装个service,daemon-reload一下。拿zero举例,

sudo vim /etc/systemd/system/door_open.service

[Unit] Description=Door Sensor Sender (Pi Zero) After=network-online.target Wants=network-online.target [Service] Type=simple User=pi WorkingDirectory=/home/pi ExecStart=/usr/bin/python3 /home/pi/door_open.py Restart=always RestartSec=2 [Install] WantedBy=multi-user.target
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 12:49:36

MySQL 中什么是条件注释

很多同学写 SQL 的时候,都熟悉 #、--、/* */ 这几种普通注释。普通注释的特点很简单:数据库解析时直接忽略里面的内容,不会执行。 但 MySQL 里有一类特殊注释,在 MySQL 环境下注释内部的 SQL 会被执行;其他数据库&…

作者头像 李华
网站建设 2026/10/3 12:47:27

PHP项目复盘:foreach 引用残留造成的诡异数据错乱

写PHP业务久的人,基本都碰到过一类完全无解的问题:数组循环处理完之后,后续操作数据莫名被篡改,代码看着干干净净,没有赋值、没有覆盖,结果就是不对。 这类问题特别喜欢出现在列表处理、批量改状态、数据组…

作者头像 李华