video intercom 配置互操作性规范 - housekeeper-software/tech GitHub Wiki
概要
各端尽量使用相同的配置存储格式,以便实现互操作性。
基本配置,basic.json
平台并没有这个配置,纯本机配置,记录平台的访问地址相关信息,以及设备编码。 还有一个displayName目前没有暴露给UI,但在完全离线使用的时候,我们需要这个字段,因为房号表中没有关于自己的描述。
{
"basic":{
"server":{
"host":"192.168.180.16",
"port":8080,
"tls":false,
"publicKey":"12345678",
"secret":"fDB7nvTg",
"enable":true
},
"deviceId":"05T-000001C-01Z-001B-001U-001F-01E",
"displayName":"1001" #这个目前在UI上没有呈现,但离线使用的时候会有用
}
}
mqtt配置,mqtt.json
这个平台也有相同的,如果平台有更新,直接覆盖本地
{
"mqtt": {
"enable": true,
"host": "10.10.6.188",
"port": 1883,
"tls": false,
"userName": "admin",
"password": "public",
"heartbeat": 20
}
}
table 房号表配置,table.json
这个平台也有,可能会被平台的覆盖。如果脱机使用,本地UI可以按照这个格式添加被叫的设备信息
{
"table": [
{
"deviceId": "05T-000001C-01Z-001B-001U-001F-01E",
"userId": "srv-05T-000001C-01Z-001B-001U-001F-01E",
"ip": "192.168.180.71",
"alias": "05T-000001C-01Z-001B-001U-001F-01E"
},
{
"deviceId": "01T-000001C-01Z-001B-001U-001F-0101N-02E",
"userId": "cwj-0005",
"ip": "192.168.180.166",
"alias": "01T-000001C-01Z-001B-001U-001F-0101N-02E"
},
{
"deviceId": "01T-000001C-01Z-001B-001U-001F-0101N-01E",
"userId": "cwj-0001",
"ip": "192.168.180.188",
"alias": "01T-000001C-01Z-001B-001U-001F-0101N-01E"
}
]
}
呼叫配置, callSettings.json
这个平台也有,可能被平台覆盖
{
"callSettings": {
"timeLimits": {
"maxRingTime": 30,
"maxConnectTime": 120,
"maxMonitorTime": 120
}
}
}
全局配置, config.json
这个平台也有,可能被平台覆盖
{
"config": {
"unlock": {
"dtmf": "#,*",
"message": "unlock"
},
"password": {
"adminPassword": "654321",
"sharedPwd": "",
"holdPwd": ""
},
"common": {
"closeDoorDelay": 10,
"screenOffDelay": 60
}
}
}
SIP profile,有关sip的配置, sip.json
这个平台没有,是本地的配置,对应于设置页面。将SIP账号和服务器的配置组装在一起。 一般情况下,平台上账号和SIP服务器是分开存储的,如果要更新,也只是分别更新。设备端要将平台的信息分别更新到这个本地配置中对应字段。 本地SIP协议栈工作的时候,只使用这个配置文件。
{
"sip": [ {
"account": {
"displayName": "xx",
"password": "xx",
"userId": "xx",
"userName": "axxE"
},
"enable": false,
"id": "mobile",
"server": {
"dialPrefix": "",
"enableRegistration": false,
"expires": 300,
"port": 0,
"proxy": "",
"realm": "",
"stun": "",
"transport": ""
}
}, {
"enable": true,
"id": "p2p",
"server": {
"dialPrefix": "",
"enableRegistration": true,
"expires": 300,
"port": 5060,
"proxy": "",
"realm": "",
"stun": "",
"transport": "udp"
}
}, {
"account": {
"displayName": "xxE",
"password": "xx",
"userId": "srv-xx",
"userName": "srv-xx01E"
},
"enable": true,
"id": "server",
"server": {
"dialPrefix": "",
"enableRegistration": true,
"expires": 300,
"port": 0,
"proxy": "xx:18888",
"realm": "",
"stun": "",
"transport": "tcp"
}
}, {
"account": {
"displayName": "xx-01E",
"password": "xx",
"userId": "tel-xxxE",
"userName": "tel-xx"
},
"enable": true,
"id": "telephone",
"server": {
"dialPrefix": "1112",
"enableRegistration": true,
"expires": 300,
"port": 0,
"proxy": "xx:18888",
"realm": "",
"stun": "",
"transport": "tcp"
}
} ]
}
设备通用配置,common.json
这个平台没有,各端也不尽相同。以下是别墅门口机关于音量和音效语言的配置
{
"volume":{
"media":60,
"voip":30
},
"voice":{
"current":"zh-cn",
"lang":[
"zh-cn",
"en-us"
]
}
}
平台存储的本机SIP账号列表,sipAccounts.json
{
"sipAccounts":[
{
"id":"server",
"account":{
"userId":"srv-1",
"userName":"srv-1",
"password":"1",
"displayName":"05T-000001C-01Z-001B-001U-001F-01E"
}
},
{
"id":"mobile",
"account":{
"userId":"app-1",
"userName":"app-1",
"password":"1",
"displayName":"05T-000001C-01Z-001B-001U-001F-01E"
}
},
{
"id":"telephone",
"account":{
"userId":"tel-1E",
"userName":"tel-1",
"password":"1",
"displayName":"05T-000001C-01Z-001B-001U-001F-01E"
}
}
]
}
平台上存储的SIP服务器配置,sipServers.json
{
"sipServers":[
{
"enable":true,
"id":"p2p",
"server":{
"dialPrefix":"",
"enableRegistration":true,
"expires":300,
"port":5060,
"proxy":"",
"realm":"",
"stun":"",
"transport":"udp"
}
},
{
"enable":true,
"id":"server",
"server":{
"dialPrefix":"",
"enableRegistration":true,
"expires":300,
"port":0,
"proxy":"x:18888",
"realm":"",
"stun":"",
"transport":"tcp"
}
},
{
"enable":true,
"id":"telephone",
"server":{
"dialPrefix":"1112",
"enableRegistration":true,
"expires":300,
"port":0,
"proxy":"x:18888",
"realm":"",
"stun":"",
"transport":"tcp"
}
}
]
}
使用原则
1) callSettings.json, config.json,table.json,mqtt.json,如果平台有更新,直接覆盖本地,
也就是说这些配置部分平台和本地,都是一份数据。谁都可以更新。但如果平台有设置,在同步时会被平台覆盖。
2) 平台上 sipAccounts.json, sipServers.json各自包含部分数据,如果需要更新的话,只能将这些数据解析出来,分别插入本地的sip.json
然后在根据情况,重启本地SIP协议栈。目前,设备端默认不需要更新这个。只在初始化之后存储到本地。
以别墅门口机的数据存储为例
别墅门口机因为处理的数据量不大,一般只对应一个房间,可能有多个室内机。因而没有使用sqlite之类的,存储时只用到了google LevelDB,这个一个高效的 KV存储,类似redis。
key的命名规则,字段中间以'#'连接。
cms#sipAccounts
cms#sipSevers
conf#basic
conf#callSettings
conf#config
conf#mqtt
conf#sip
conf#table
data#card#000001C-01Z-001B-001U
data#face#000001C-01Z-001B-001U
data#password#000001C-01Z-001B-001U
data#telephone#000001C-01Z-001B-001U
cms#开头的保存的是平台给的有关SIP账号和SIP服务器的配置,本地不会使用,只是在同步时计算下hash值而已。当平台有更新时,在更新过程中已经
将数据解析插入到 conf#sip配置中,然后将conf#sip在序列化为json,更新到数据库。之后,这两个cms#开头的配置已经没有用了。
conf#开头的都是设备运行时需要加载到内存中使用的配置。在数据同步时,如果平台有相同的配置,则直接将平台的json写入相同key的数据库中即可。
data#开头的是门禁相关的数据,因为平台以单元为单位存储,这里的key中也包含单元的信息。当平台同步时,根据data.json查找到本地的key,校验hash,
如果hash一致,则说明这个单元的数据没有变化,不需要更新,如果不一致则先同步到本地,然后再删除本地这个单元的数据,然后再添加到本地库。
参考
可以参考如下的源码:
content/config_manager.cc : 包含本机如何从本地KV数据库加载各项配置,以及如何更新
content/data_manager.cc : 包含本地如何从本地KV数据库加载人脸卡片等信息,以及如何更新
content/web/web_get_data.cc :包含对data#内容的更新,只对室外机有效。
content/data_download.cc:包含所有的平台同步
content/content_main.cc:
void ContentMain::ProcessDataMessage(const std::string &name,
const base::DictionaryValue *params) {
包含如何处理平台更新的配置和数据,以及如何响应平台。
}
bool ContentMain::ProcessLocalWebApi(const std::string &name,
const std::string &data) {
这里处理本机设置页面的数据
}
void ContentMain::OnMqttMessage(const std::string &topic, std::unique_ptr<mqtt::MqttRecvPacket> packet) {
//这里是室外机处理 MQTT消息的流程
}