鸿蒙智能快递柜取件助手开发指南 原创

进修的泡芙
发布于 2025-6-20 14:44
浏览
0收藏

鸿蒙智能快递柜取件助手开发指南

一、系统架构设计

基于HarmonyOS的智能快递柜取件助手,利用短信识别和分布式能力实现以下功能:
短信识别:自动解析短信中的取件码和快递柜位置

跨设备同步:手机识别取件码,大屏展示取件信息

一键开柜:支持远程开柜操作

取件提醒:智能提醒未取快递

!https://example.com/harmony-parcel-helper-arch.png

二、核心代码实现
短信解析服务

// SmsParserService.ets
import sms from ‘@ohos.telephony.sms’;
import distributedData from ‘@ohos.distributedData’;

class SmsParserService {
private static instance: SmsParserService = null;
private dataManager: distributedData.DataManager;
private parcelListeners: ParcelListener[] = [];

private constructor() {
this.initDataManager();
this.initSmsListener();
public static getInstance(): SmsParserService {

if (!SmsParserService.instance) {
  SmsParserService.instance = new SmsParserService();

return SmsParserService.instance;

private initDataManager(): void {

this.dataManager = distributedData.createDataManager({
  bundleName: 'com.example.parcelhelper',
  area: distributedData.Area.GLOBAL,
  isEncrypted: true
});

this.dataManager.registerDataListener('parcel_sync', (data) => {
  this.handleSyncData(data);
});

private initSmsListener(): void {

try {
  sms.on('smsReceive', (data) => {
    this.parseSms(data.message);
  });

catch (err) {

  console.error('初始化短信监听失败:', JSON.stringify(err));

}

private parseSms(message: string): void {
// 常见快递柜短信格式正则匹配
const patterns = [
/取件码(\d{4,6})[\s,,]+请至(.+?)快递柜取件/i,
/验证码:(\d{4,6})[\s,,]+地址:(.+?)快递柜/i,
/【(.+?)】您的取件码是(\d{4,6})[\s,,]+请到(.+?)取件/i
];

let code = '';
let location = '';
let carrier = '';

for (const pattern of patterns) {
  const match = message.match(pattern);
  if (match) {
    if (match.length >= 3) {
      code = match[1];
      location = match[2];

if (match.length >= 4) {

      carrier = match[1];

break;

}

if (code && location) {
  const parcelInfo: ParcelInfo = {
    id: Date.now().toString(),
    code: code,
    location: location,
    carrier: carrier || '未知快递',
    receiveTime: Date.now(),
    status: '待取件',
    message: message
  };
  
  this.notifyParcelFound(parcelInfo);
  this.syncParcelInfo(parcelInfo);

}

private notifyParcelFound(info: ParcelInfo): void {
this.parcelListeners.forEach(listener => {
listener.onParcelFound(info);
});
private syncParcelInfo(info: ParcelInfo): void {

this.dataManager.syncData('parcel_sync', {
  type: 'parcel_info',
  info: info,
  timestamp: Date.now()
});

private handleSyncData(data: any): void {

if (!data || data.type !== 'parcel_info') return;

this.parcelListeners.forEach(listener => {
  listener.onParcelFound(data.info);
});

public addParcelListener(listener: ParcelListener): void {

if (!this.parcelListeners.includes(listener)) {
  this.parcelListeners.push(listener);

}

public removeParcelListener(listener: ParcelListener): void {
this.parcelListeners = this.parcelListeners.filter(l => l !== listener);
}

interface ParcelListener {
onParcelFound(info: ParcelInfo): void;
interface ParcelInfo {

id: string;
code: string;
location: string;
carrier: string;
receiveTime: number;
status: ‘待取件’ ‘已取件’
‘已过期’;
message: string;
export const smsService = SmsParserService.getInstance();

快递柜控制服务

// LockerControlService.ets
import distributedData from ‘@ohos.distributedData’;
import http from ‘@ohos.net.http’;

class LockerControlService {
private static instance: LockerControlService = null;
private dataManager: distributedData.DataManager;
private controlListeners: ControlListener[] = [];

private constructor() {
this.initDataManager();
public static getInstance(): LockerControlService {

if (!LockerControlService.instance) {
  LockerControlService.instance = new LockerControlService();

return LockerControlService.instance;

private initDataManager(): void {

this.dataManager = distributedData.createDataManager({
  bundleName: 'com.example.parcelhelper',
  area: distributedData.Area.GLOBAL,
  isEncrypted: true
});

this.dataManager.registerDataListener('locker_sync', (data) => {
  this.handleSyncData(data);
});

public async openLocker(lockerId: string, code: string): Promise<boolean> {

try {
  // 实际应用中应调用快递柜API
  const httpRequest = http.createHttp();
  const response = await httpRequest.request(
    'https://api.example.com/open-locker',

method: ‘POST’,

      header: { 'Content-Type': 'application/json' },
      extraData: JSON.stringify({ lockerId, code })

);

  if (response.responseCode === 200) {
    const result = JSON.parse(response.result);
    if (result.success) {
      this.syncLockerStatus(lockerId, 'opened');
      return true;

}

  return false;

catch (err) {

  console.error('开柜请求失败:', JSON.stringify(err));
  return false;

}

private syncLockerStatus(lockerId: string, status: string): void {
this.dataManager.syncData(‘locker_sync’, {
type: ‘locker_status’,
lockerId: lockerId,
status: status,
timestamp: Date.now()
});
private handleSyncData(data: any): void {

if (!data) return;

switch (data.type) {
  case 'locker_status':
    this.controlListeners.forEach(listener => {
      listener.onLockerStatusChange(data.lockerId, data.status);
    });
    break;
  
  case 'open_request':
    this.handleOpenRequest(data.fromDevice, data.lockerId, data.code);
    break;

}

private handleOpenRequest(fromDevice: string, lockerId: string, code: string): void {
// 显示确认对话框
const dialog = new AlertDialog({
title: ‘开柜请求’,
message: 设备 {fromDevice} 请求打开 {lockerId} 快递柜,
buttons: [
text: ‘允许’,

      action: async () => {
        const success = await this.openLocker(lockerId, code);
        prompt.showToast({ 
          message: success ? '开柜成功' : '开柜失败' 
        });

},

text: ‘拒绝’,

      action: () => {
        prompt.showToast({ message: '已拒绝请求' });

}

});

dialog.show();

public async requestOpenLocker(deviceId: string, lockerId: string, code: string): Promise<void> {

this.dataManager.syncData('locker_sync', {
  type: 'open_request',
  fromDevice: this.dataManager.getDeviceId(),
  lockerId: lockerId,
  code: code,
  timestamp: Date.now()
});

public addControlListener(listener: ControlListener): void {

if (!this.controlListeners.includes(listener)) {
  this.controlListeners.push(listener);

}

public removeControlListener(listener: ControlListener): void {
this.controlListeners = this.controlListeners.filter(l => l !== listener);
}

interface ControlListener {
onLockerStatusChange(lockerId: string, status: string): void;
export const lockerService = LockerControlService.getInstance();

主界面实现

// MainScreen.ets
import { smsService } from ‘./SmsParserService’;
import { lockerService } from ‘./LockerControlService’;

@Component
export struct MainScreen {
@State parcels: ParcelInfo[] = [];
@State selectedParcel: ParcelInfo | null = null;
@State connectedDevices: string[] = [];

build() {
Column() {
// 标题栏
Row() {
Text(‘智能快递柜取件助手’)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)

    Button('协同')
      .width(80)
      .onClick(() => {
        this.showDeviceSelector();
      })

.padding(10)

  .width('100%')
  
  // 快递列表
  if (this.parcels.length === 0) {
    Column() {
      Image($r('app.media.ic_empty'))
        .width(120)
        .height(120)
        .margin({ bottom: 20 })
      
      Text('暂无待取快递')
        .fontSize(16)

.width(‘100%’)

    .height('60%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)

else {

    List() {
      ForEach(this.parcels, (parcel) => {
        ListItem() {
          Column() {
            Row() {
              Text(parcel.carrier)
                .fontSize(18)
                .fontWeight(FontWeight.Bold)
                .layoutWeight(1)
              
              Text(this.formatTime(parcel.receiveTime))
                .fontSize(12)
                .fontColor('#666666')

.margin({ bottom: 8 })

            Row() {
              Text(取件码: ${parcel.code})
                .fontSize(16)
                .layoutWeight(1)
              
              Text(parcel.status === '待取件' ? '待取件' : '已取件')
                .fontSize(14)
                .fontColor(parcel.status === '待取件' ? '#FF9800' : '#4CAF50')

Text(parcel.location)

              .fontSize(14)
              .fontColor('#666666')
              .margin({ top: 8 })

.padding(15)

          .width('100%')
          .borderRadius(8)
          .backgroundColor(this.selectedParcel?.id === parcel.id ? '#E3F2FD' : Color.White)

.onClick(() => {

          this.selectedParcel = parcel;
        })
      })

.height(‘60%’)

    .margin({ bottom: 20 })

// 控制区域

  if (this.selectedParcel) {
    Column() {
      Button('一键开柜')
        .width('80%')
        .height(50)
        .margin({ bottom: 10 })
        .onClick(() => {
          this.openSelectedLocker();
        })
      
      Button('分享取件码')
        .width('80%')
        .height(50)
        .onClick(() => {
          this.shareParcelInfo();
        })

}

  // 设备连接状态
  if (this.connectedDevices.length > 0) {
    Column() {
      Text('已连接设备')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 8 })
      
      ForEach(this.connectedDevices, (device) => {
        Text(device)
          .fontSize(14)
          .margin({ bottom: 4 })
      })

.padding(10)

    .width('90%')
    .backgroundColor('#F5F5F5')
    .borderRadius(8)
    .margin({ top: 20 })

}

.width('100%')
.height('100%')
.padding(20)
.onAppear(() => {
  smsService.addParcelListener({
    onParcelFound: (info) => {
      this.addParcel(info);

});

  lockerService.addControlListener({
    onLockerStatusChange: (lockerId, status) => {
      this.updateLockerStatus(lockerId, status);

});

})
.onDisappear(() => {
  smsService.removeParcelListener({
    onParcelFound: () => {}
  });
  
  lockerService.removeControlListener({
    onLockerStatusChange: () => {}
  });
})

private addParcel(info: ParcelInfo): void {

// 避免重复添加
if (!this.parcels.some(p => p.id === info.id || 
    (p.code = info.code && p.location = info.location))) {
  this.parcels = [info, ...this.parcels];

}

private updateLockerStatus(lockerId: string, status: string): void {
if (status === ‘opened’ && this.selectedParcel) {
this.parcels = this.parcels.map(p => {
if (p.id === this.selectedParcel?.id) {
return { …p, status: ‘已取件’ };
return p;

  });
  
  this.selectedParcel = null;
  prompt.showToast({ message: '取件成功' });

}

private openSelectedLocker(): void {
if (!this.selectedParcel) return;

lockerService.openLocker(
  this.selectedParcel.location,
  this.selectedParcel.code
).then(success => {
  prompt.showToast({ 
    message: success ? '开柜请求已发送' : '开柜请求失败' 
  });
});

private shareParcelInfo(): void {

if (!this.selectedParcel) return;

const devices = ['设备1', '设备2', '设备3']; // 实际应从设备管理服务获取
const dialog = new AlertDialog({
  title: '分享到设备',
  items: devices,
  onSelect: (index) => {
    this.sendToDevice(devices[index]);

});

dialog.show();

private sendToDevice(deviceId: string): void {

if (!this.selectedParcel) return;

lockerService.requestOpenLocker(
  deviceId,
  this.selectedParcel.location,
  this.selectedParcel.code
);

prompt.showToast({ message: 已分享到 ${deviceId} });

private showDeviceSelector(): void {

const devices = ['设备1', '设备2', '设备3']; // 实际应从设备管理服务获取
const dialog = new AlertDialog({
  title: '选择协同设备',
  items: devices,
  onSelect: (index) => {
    this.connectToDevice(devices[index]);

});

dialog.show();

private connectToDevice(deviceId: string): void {

if (!this.connectedDevices.includes(deviceId)) {
  this.connectedDevices.push(deviceId);
  prompt.showToast({ message: 已连接 ${deviceId} });

}

private formatTime(timestamp: number): string {
const date = new Date(timestamp);
return {date.getMonth()+1}/{date.getDate()} {date.getHours()}:{date.getMinutes().toString().padStart(2, ‘0’)};
}

三、项目配置与权限
权限配置

// module.json5
“module”: {

"requestPermissions": [

“name”: “ohos.permission.RECEIVE_SMS”,

    "reason": "读取短信获取取件码"
  },

“name”: “ohos.permission.INTERNET”,

    "reason": "连接快递柜服务"
  },

“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,

    "reason": "同步取件信息"
  },

“name”: “ohos.permission.ACCESS_DISTRIBUTED_DEVICE_MANAGER”,

    "reason": "发现和连接其他设备"

],

"abilities": [

“name”: “MainAbility”,

    "type": "page",
    "visible": true
  },

“name”: “LockerAbility”,

    "type": "service",
    "backgroundModes": ["dataTransfer"]

]

}

四、总结与扩展

本智能快递柜取件助手实现了以下核心功能:
智能识别:自动解析短信中的取件信息

便捷取件:一键操作快速开柜

多设备协同:家庭成员共享取件信息

状态同步:实时更新取件状态

扩展方向:
快递追踪:整合物流信息追踪

代取服务:授权他人代取快递

批量取件:支持多件快递同时取出

历史记录:保存取件记录便于查询

社区服务:与物业系统对接提供增值服务

通过HarmonyOS的分布式能力和短信识别功能,我们构建了一个便捷、高效的快递取件解决方案,大大简化了快递取件流程。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐