# octans-device-sdk **Repository Path**: watertreestar/octans-device-sdk ## Basic Information - **Project Name**: octans-device-sdk - **Description**: 定位相关设备接入SDK - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2023-08-15 - **Last Updated**: 2025-04-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 设备通信SDK ## supported - [x] 设备状态管理 - [x] 获取在线设备 - [x] 气体检测器 - [x] 添加删除设备 - [x] 传感器值事件上报 - [x] 心跳检测 - [ ] NVR和IPC - [x] 主动发现内网的IPC设备(onvif协议) - [x] 添加删除设备 - [x] 获取拉流地址(onvif协议) - [ ] 添加IPC到NVR的通道 - [x] 心跳检测 - [x] 人脸识别面板机 - [x] 下发指令 - [x] 识别事件上报 - [x] 心跳检测 - [x] 车行门禁控制卡 - [x] 发现门禁控制卡 - [x] 添加删除设备 - [x] 刷卡事件上报 - [x] 创建删除权限 - [x] 清空权限 - [x] 心跳检测 ## install ```bash go get -u gitee.com/watertreestar/octans-device-sdk ``` ## auto discovery | **设备** | **自动发现** | |:-----------:|:------------:| | 气体传感器 | 不支持 | | 人脸识别面板 | 不支持 | | 网络摄像机 | 支持 | | 车行门禁控制器 | 支持 | ## get started 首先使用下面这段代码初始化设备connector并启动服务 ```go device.Run(device.ConnectorConfiguration{ PanelPort: 5012, // 人脸识别机接入HTTP端口 VehiclePort: 60005, // 车行控制门禁接入UDP端口 Logger: &logger{}, // 设备状态变更回调, name为设备SN号, online: true-表示变更为在线 false-表示变更为离线 StatusChangeCallback: func (name string, online bool) { fmt.Printf("[%s]设备状态:%s", name, online) }, }) ``` ## 获取在线设备sn列表 ```go go func() { onlineDevice := device.OnlineDevice() fmt.Printf("当前在线设备sn: %v \n", onlineDevice) }() ``` 然后可以使用device.Gas(气体检测), device.Ipc(网络摄像机),device.Panel(人脸识别面板机),device.Vehicle(车行蓝牙控制卡) 来和具体设备通信 ### 气体检测设备 - 气体传感设备通过服务器主动pull的方式获取数值,目前pull的间隔为10s, 如果成功读取值,同时更新上次心跳时间 - 如果30s都没有心跳,则认为下线 ```go func testGas() { // 添加删除其它检测设备,并读取气体检测值 valChan := device.Gas.GetValChan() err := device.Gas.AddDevice("123", "192.168.236.70", 8200, 4) if err != nil { fmt.Printf("%v\n", err) } go func() { for v := range valChan { fmt.Printf("env val: %v\n", v) } }() time.Sleep(time.Second * 30) err = device.Gas.RemoveDevice("123") if err != nil { fmt.Printf("删除气体检测设备错误%s \n", err) } } ``` ### 网络摄像头IPC - 海康IPC在激活后默认不开启onvif协议,需要手动开启并配置访问用户名密码 - 海康onvif协议访问的用户名密码和管理员密码不同 ```go func testIpc() { // 通过onvif发现设备 // 通过onvif获取拉流地址 // 添加onvif设备,为了监控状态 devices, err := device.Ipc.Discovery() if err != nil { fmt.Printf("%v \n", err) } fmt.Printf("发现的onvif设备列表:%s \n", devices) for _, d := range devices { device.Ipc.AddDevice(d.ID, d.XAddr, "admin", "ipc@2023") url, err := device.Ipc.GetStreamUrl("http://192.168.236.104/onvif/device_service", "admin", "ipc@2023") if err != nil { fmt.Printf("%v \n", err) continue } fmt.Println(url) } } ``` ### 人脸识别面板机 - 设备心跳维护时间为3分钟 ```go func testPanel() { panel := device.Panel // 添加设备 err := panel.AddDevice("p-1222", "AB4F4C9B-0EB55155") if err != nil { fmt.Printf("add panel device error, %v", err) return } // 读取刷卡结果 resultChan := panel.GetResultChan() go func() { for result := range resultChan { fmt.Printf("%v", result) } }() // 发送指令,并阻塞等待返回结果, 结果中具体的内容参考协议文档 // 参数说明: // 第一个参数为sn: 人脸识别相机的序列号 // 第二个参数为协议内容,字段参考文档,不用写index和version字段 // 第三个参数为等待返回的超时时间 result, err := panel.Send("p-1222", map[string]interface{}{ "cmd": "create_face", //创建人员指令 "per_id": "ff00ff", //人员id:不超过32位 "face_id": "ff00ff", //人脸 ID(不填则自动生成)(可选) "per_name": "tony", //姓名:不超过10字节 utf8编码 "idcardNum": "1234", //韦根号,智能卡号(可选) "img_data": "fgfsgfs", //base64 "idcardper": "51102419999999171x", //身份证号:18位(可选) "s_time": 0, //启用日期时间戳(可选) "e_time": 1000, //有效日期时间戳(可选) "per_type": 0, //0:普通人员; 1:白名单人员;2:黑名单人员(可选) "usr_type": 0, //权限类型,取值 0 - 5,默认 0(可选) "auth_type": 0, //拓展权限,取值1-50,默认0(可选) }, time.Second*5) if err != nil { fmt.Printf("send data error, %v", err) return } fmt.Printf("%v", result) } ``` ### 车行门禁控制卡 - 刷卡事件为控制器主动向服务器上报,所以需要使用软件工具配置服务器IP地址端口 - 服务器每10s主动获取控制卡状态,并以此作为心跳续约,超过3分钟没有心跳则认为下线 - serialNum为控制卡序列号,通过自动发现或者工具搜索到设备后可以获取该值 - 添加权限的卡号拥有所有门的权限 - 经过测试,卡片处在范围内会触发多次刷卡事件,所以设置了一个30s的去抖动窗口,30s内的多次刷卡只有第一次的事件有效 ```go func testVehicle() { ve := device.Vehicle sdevices, err := ve.Discovery() if err != nil { fmt.Printf("discovery vehicle err: %v \n", err) return } fmt.Printf("车行门禁控制卡数量: %d \n", len(sdevices)) for _, d := range sdevices { fmt.Printf("发现设备:%v \n", d) if err := ve.AddDevice("ve-123", d.SerialNum, d.IP); err != nil { fmt.Println(err) continue } } // 清空所有权限 err = ve.ClearPrivilege("ve-123") if err != nil { fmt.Println(err) } // 添加卡号权限 err = ve.AddPrivilege("ve-123", 3671303) if err != nil { fmt.Printf("添加权限失败 %v", err) } go func() { // 20s后删除该卡号的权限 <-time.NewTimer(time.Second * 20).C err := ve.RemovePrivilege("ve-123", 3671303) if err != nil { fmt.Printf("删除权限失败 %v", err) } }() // 读取刷卡事件 eventchan := ve.GetSwipeEvent() for data := range eventchan { fmt.Println(data) } } ``` ## Q&A 1. 微耕控制器(车行)在配置接收事件的服务器后,服务器接收不到刷卡事件? 完成接收服务器设置后,需要该服务器发送一次协议报文,经过测试,给控制器发送获取状态的报文后,就可以正确接收到事件。但是在该SDK中已经做了这方面的处理,使用者无需关系 2. 自动发现功能为什么发现不了设备? 自动发现依赖于UDP广播,所以需要检查所在主机是否设置了防火墙导致接收不到广播响应报文 3. 使用SDK为什么要AddDevice/RemoveDevice操作? 为了维护某个设备的心跳