Appearance
IP电子围栏:设备离开指定区域自动告警
"电子围栏"这个词听着很高大上,其实在共享设备、物联网、资产管理这些场景里,用IP定位就能做一个低成本版本:设备换了个城市,自动告警。
这篇讲讲思路和代码。核心原理不复杂:定时查设备IP归属地,跟"设备应在的城市"对比,不一致就报警。
什么时候需要这东西
- 共享充电宝/共享单车:设备被搬去别的城市了;
- 企业资产:笔记本电脑、服务器离开指定区域;
- 物联网设备:传感器、车载终端位置漂移监控;
- 门禁/考勤:员工在公司网络外登录办公系统。
这些场景的共同点:设备没有GPS(或不想用GPS),但想知道它"大概在不在应该待的地方"。
核心逻辑
python
import requests
import time
def check_device(device_id, ip, expected_city):
r = requests.get(f"https://ip9.com.cn/get?ip={ip}", timeout=3)
d = r.json()
if d.get("ret") != 200:
return "unknown" # 查不到,标记待确认
info = d["data"]
city = info.get("city") or info.get("prov")
if city == expected_city:
return "ok"
# 城市变了 -> 告警
alert(device_id, f"设备离开预期区域: {city}")
return "moved"expected_city 就是设备登记的"应在地"。每次设备上报IP,就查一次对比。
注意:别一有偏差就报警
这是电子围栏最容易做砸的地方。IP定位的精度是"城市级",边界情况很多:
- 设备在城市交界处,IP可能在隔壁城市显示;
- 运营商网络原因,IP短暂跳变;
- 动态IP本来就会变。
所以正确做法是**"阈值 + 容忍"**:
python
def check_with_tolerance(device_id, ip, expected_city, history):
city = query_city(ip)
# 记录最近N次
history[device_id].append(city)
history[device_id] = history[device_id][-5:]
# 最近5次里有3次以上都偏离 -> 才告警
if sum(1 for c in history[device_id] if c != expected_city) >= 3:
alert(device_id, f"设备已离开 {expected_city}")
return True
return False"连续多次都偏移"才告警,能过滤掉大部分误报。
更精细:按省份判断 + 距离
如果设备是"跨省才算异常",就用 prov 判断;如果设备不能离得太远,可以用 lng/lat 算一下"设备城市中心"和"应在地城市中心"的距离:
python
import math
def city_distance(lat1, lng1, lat2, lng2):
R = 6371
p1, p2 = math.radians(lat1), math.radians(lat2)
dp = p2 - p1
dl = math.radians(lng2 - lng1)
a = math.sin(dp/2)**2 + math.cos(p1)*math.cos(p2)*math.sin(dl/2)**2
return 2 * R * math.asin(math.sqrt(a))
# 若设备应在地与当前IP城市中心距离超过阈值,则告警
if city_distance(dc_lat, dc_lng, ip_lat, ip_lng) > 200: # 超过200公里
alert(...)注意这只是"城市中心到城市中心"的距离,别拿它当设备真实移动距离。
告警渠道
告警发到哪?几种常见选择:
- 钉钉/企业微信/飞书机器人 webhook(最快);
- 邮件(低频场景够用);
- 短信(高优先级才用,有成本)。
python
def alert(device_id, msg):
# 钉钉机器人示例
webhook = "https://oapi.dingtalk.com/robot/send?access_token=xxx"
requests.post(webhook, json={
"msgtype": "text",
"text": {"content": f"[设备告警] {device_id}: {msg}"}
})一个完整的巡检
可以用定时任务,每分钟把"在线设备"的IP批量查一遍(复用我"Python批量查询"那篇的脚本):
python
def patrol(devices):
for dev in devices:
if dev.is_online:
check_with_tolerance(dev.id, dev.ip, dev.expected_city, history)批量查询记得去重+缓存,别把接口打到限流。
说点实在的
IP电子围栏的精度就是"城市级到省市级",它能帮你发现"设备被搬到另一个城市"这种大动作,发现不了"设备挪了个小区"。明确它能干的事,别指望它干精确到米的活,那得靠GPS。
对共享设备、资产盘点这类"看大方向"的场景,这套已经够用了。