日志管理

门锁的记录有三类:相册记录、告警记录、日志记录。

相册记录

  • 支持视频和图片抓拍的锁会有此类记录,因此记录中会包含有图片和视频,一般会在有人按门铃、有人逗留等情况产生;
  • 出于安全风险考虑,涂鸦会对图片和视频进行加密处理,开发者需要使用特定的能力及方案才能正常展示。

图片处理方案请参数: 多媒体图片处理

视频处理方案请参数: 多媒体图片处理

告警记录

门锁告警时产生的记录,包含如:防撬、密码试错、指纹试错、逗留、劫持、低电量等告警

日志记录

记录类型有

  • close_record 表示关锁日志
  • unlock_record 表示开锁日志
  • operation 操作类日志
  • local_operation 设备本地操作日志
  • dev_bind 设备绑定日志

日志文案处理

告警处理


export const codeOnlyShowDpCodeText = [
  'doorbell',
  'unlock_offline_clear',
  'unlock_offline_clear_single',
];
const getText = (log) => {
    const text = codeOnlyShowDpCodeText.includes(log.dpCode)
        ? Strings.getDpLang(log.dpCode)
        : Strings.getDpLang(log.dpCode, log.data as string);
    if (log.isHijack) {
        // 是否劫持
        return `${Strings.getDpLang('hijack')}【${text}】`;
    }
    return text;
}

关锁日志

const text = Strings.getLang(`locked_${log.closeValue}`);

本地操作记录


import {
  LocalOperateCategory,
  LocalSettingData,
  LocalUnlockMethodData,
  LogData,
} from '@ray-js/lock-sdk';

const getLocalOperationText = (log: LogData) => {
  if (!log.localRecord) {
    return Strings.getLang('unkownLocalOperation');
  }

  const { category, userId, userType, toUserType, toUserId } = log.localRecord;
  switch (category) {
    case LocalOperateCategory.DELETE_UNLOCK_METHOD: {
      const { unlockMethod, unlockId, isRemoveAll } = log.localRecord as LocalUnlockMethodData;
      if (isRemoveAll) {
        return Strings.formatValue(
          'localDeleteAllUnlockMethod',
          Strings.getLang(`localUser${userType}`),
          userId,
          Strings.getLang(`localUser${toUserType}`),
          toUserId,
          Strings.getLang(unlockMethod)
        );
      }
      return Strings.formatValue(
        'deleteUnlockMethod',
        Strings.getLang(`localUser${userType}`),
        userId,
        Strings.getLang(`localUser${toUserType}`),
        toUserId,
        Strings.getLang(unlockMethod),
        unlockId
      );
    }
    case LocalOperateCategory.ADD_UNLOCK_METHOD: {
      const { unlockMethod, unlockId } = log.localRecord as LocalUnlockMethodData;
      return Strings.formatValue(
        'localAddUnlockMethod',
        Strings.getLang(`localUser${userType}`),
        userId,
        Strings.getLang(`localUser${toUserType}`),
        toUserId,
        Strings.getLang(unlockMethod),
        unlockId
      );
    }
    case LocalOperateCategory.MODIFY_UNLOCK_METHOD: {
      const { unlockMethod, unlockId } = log.localRecord as LocalUnlockMethodData;
      return Strings.formatValue(
        'localModifyUnlockMethod',
        Strings.getLang(`localUser${userType}`),
        userId,
        Strings.getLang(`localUser${toUserType}`),
        toUserId,
        Strings.getLang(unlockMethod),
        unlockId
      );
    }
    case LocalOperateCategory.ADD_USER:
      return Strings.formatValue(
        'localAddUser',
        Strings.getLang(`localUser${userType}`),
        userId,
        Strings.getLang(`localUser${toUserType}`),
        toUserId
      );
    case LocalOperateCategory.DELETE_USER:
      return Strings.formatValue(
        'localDeleteUser',
        Strings.getLang(`localUser${userType}`),
        userId,
        Strings.getLang(`localUser${toUserType}`),
        toUserId
      );
    case LocalOperateCategory.SETTING: {
      const { type, data } = log.localRecord as LocalSettingData;
      /**
       * 配置性数据多语言 key 规则:
       * 名称 key: localSetting_{type};
       * 值 key: localSetting_{type}_{data};
       */
      if (typeof data === 'number') {
        return Strings.formatValue(
          'localSetting',
          Strings.getLang(`localUser${userType}`),
          userId,
          // @ts-expect-error
          Strings.getLang(`localSetting_${type}`),
          // @ts-expect-error
          Strings.getLang(`localSetting_${type}_${data}`)
        );
      }
      return Strings.formatValue(
        'localSetting1',
        Strings.getLang(`localUser${userType}`),
        userId,
        // @ts-expect-error
        Strings.getLang(`localSetting_${type}`)
      );
    }
    default:
      return Strings.getLang('unkownLocalOperation');
  }
};

操作类日志

const {
    property: { type, scale, unit },
} = dpSchema[log.dpCode] || {};
switch (type) {
case 'value':
    return Strings.formatValue(
    'settingRecord',
    Strings.getDpLang(log.dpCode),
    `${utils.scaleNumber(scale, log.data as number)}${Strings.getDpLang(
        log.dpCode,
        'unit'
    )}`
    );
case 'enum':
    return Strings.formatValue(
    'settingRecord',
    Strings.getDpLang(log.dpCode),
    Strings.getDpLang(log.dpCode, log.data as string)
    );
case 'bool':
    return Strings.formatValue(
    'settingRecord',
    Strings.getDpLang(log.dpCode),
    Strings.getDpLang(log.dpCode, log.data as boolean)
    );
default:
    return Strings.getDpLang(log.dpCode);
}

开锁日志


import {
  getCurrentUserSync,
  LocalOperateCategory,
  LocalSettingData,
  LocalUnlockMethodData,
  LogData,
  unlockDp2Type,
} from '@ray-js/lock-sdk';

const getUnlockText = (log: LogData) => {
  const user = getCurrentUserSync();
  // 是否为组合开锁
  if (log.unionUnlockInfo?.length) {
    const logText = log.unionUnlockInfo
      .map(item => {
        let { userName } = item;
        if (item.userId === user?.userId) {
          userName = Strings.getLang('you');
        }
        return Strings.formatValue(
          'unlockFormat',
          userName,
          item.unlockName ? item.unlockName : Strings.getLang(item.type)
        );
      })
      .join('、');
    return Strings.formatValue('unionUnlock', logText);
  }
  if (log.userName && log.unlockName) {
    // 如果存在用户和解锁名称,表示是用户操作
    return Strings.formatValue(
      'unlockFormat',
      log.userId === user?.userId ? Strings.getLang('you') : log.userName,
      log.unlockName
    );
  }
  // 有名称时
  if (log.unlockName) {
    return Strings.formatValue('unlockFormat1', log.unlockName);
  }

  // 以下为无名称情况处理
  // 临时或离线密码处理
  if ([69, 89].indexOf(log.dpId) !== -1) {
    // 临时或离线密码处理
    return Strings.getDpLang(log.dpCode);
  }
  // 一些特殊的解锁
  if (codeOnlyShowDpCodeText.includes(log.dpCode)) {
    return Strings.getDpLang(log.dpCode);
  }

  // 解锁方式处理
  if (unlockDp2Type[log.dpCode]) {
    return Strings.formatValue(
      'unlockFormat2',
      Strings.getLang(unlockDp2Type[log.dpCode]),
      log.data
    );
  }

  return Strings.getDpLang(log.dpCode);
};

API

获取最近 2 条记录

  • 含义:获取最近 2条记录,包括告警、开锁、关锁、操作日志等
  • 详细:查看文档

获取日志记录

  • 含义:获取日志记录,包括开锁、关锁、操作、本地操作等日志
  • 详细:查看文档

获取告警列表

获取相册日志

注册通知可刷新日志事件

  • 含义:当收到相关的记录 DP 上报时,会触发此事件
  • 详细:查看文档

注销通知可刷新日志事件

  • 含义:注销通过 onLogsRefresh 注册的事件
  • 详细:查看文档

常见问题

Q1: 如何区分不同类型的日志?

A: 通过 type 字段区分:

  • unlock_record: 开门记录
  • close_record: 关锁记录
  • alarm_record: 告警记录
  • dev_bind: 设备绑定记录
  • local_operation: 本地操作记录

Q2: 如何判断日志是否可绑定到成员?

A: 通过 bindable 字段判断,如果为 true,表示该日志中的开锁方式可以绑定到成员。

Q3: 如何获取日志中的媒体文件?

A: 日志对象中的 mediaInfo 字段包含媒体信息,使用 getMediaUrl API 获取实际播放地址:

const mediaUrl = await getMediaUrl({
  mediaPath: log.mediaInfo[0].mediaPath,
  mediaBucket: log.mediaInfo[0].mediaBucket
});

Q4: 联合开锁信息是什么?

A: unionUnlockInfo 表示多人联合开锁的信息,包含参与开锁的用户和开锁方式信息。

Q5: 如何实现日志的实时更新?

A: 使用 onLogsRefresh 监听日志更新事件:

onLogsRefresh(() => {
  // 重新获取日志列表
  fetchLogs();
});

Q6: 相册记录支持哪些设备?

A: 相册记录仅支持视对讲设备(带摄像头的门锁设备)。

Q7: 如何获取未读日志数量?

A: 使用 getLatestLogs API,返回结果中的 unreadCount 字段表示未读数量。