65.9K
CodeProject 正在变化。 阅读更多。
Home

移动电话文件传输的简单指南

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (41投票s)

2006年3月16日

CPOL

12分钟阅读

viewsIcon

358016

downloadIcon

2003

一篇关于如何在手机上进行文件传输的文章。

目录

引言

随着手机行业的飞速发展,我们的手机比以前更加强大。如今,手机可以处理图片、声音,甚至视频。我们可以从手机的摄像头获取图片,或者从 PC 或网站下载。我有两部手机,一部是西门子 CXV65,一部是诺基亚 6021。当我想传输图片到它们时,我必须安装两个独立的软件,这很烦人。这确实占用了我大量的磁盘空间,并拖慢了我的电脑。

虽然我们可以购买商业软件来实现这一点,但我想知道是否有可能自己开发一个软件?这是一个令人惊讶的想法,但我确实完成了。现在,我将从宏观的角度告诉您我是如何做到的。在这篇文章中,您将了解什么是 OBEX、FBUS 和插件方案。我希望代码或数据示例以及源代码中的注释能给您一个清晰的认识。希望您喜欢这篇文章!

背景

在我开始这个程序之前,我使用 Visual Studio 2003 在 SMS(短消息服务)方面做了大量工作。在 .NET 1.1 下很难找到一个真正稳定且可扩展的串行端口类,因此,在这个时期,很多工作都失败了。但如今,.NET 2.0 和 .NET 2.0 Compact Framework 都在 System.IO.Ports 命名空间下为我们提供了相当不错的串行端口类,它稳定、可扩展且易于使用。所以现在,我们可以比以前更容易地编写自己的串行端口程序了。

我的两部手机都是基于串行端口的手机,提供数据线接口。西门子 CXV65 手机有两种数据线,一种是 540 数据线,另一种是 510 数据线。我都有。当插入 540 数据线时,我的 PC 会找到一个 COM3 端口上的西门子调制解调器。而 510 数据线则是一个 PL2303 USB 转串行端口的桥接器。诺基亚手机也有两种数据线,DKU-2 和 DKU-5 数据线。我的诺基亚 6021 使用 DKU-5 数据线,它也是一个 PL2303 桥接器。

正如您稍后会看到的,西门子手机使用 OBEX(Object Exchange)协议进行文件传输,而大多数诺基亚手机使用一种称为 FBUS 的协议,有些还使用 MBUS 协议。OBEX 协议有详细的文档,但 FBUS 的文档很难找到。稍后我将介绍 OBEX 和 FBUS。

我们开始吧!

看我的演示程序

完整的解决方案包含七个项目

  1. FileTransferCodeDemo

    演示项目的窗体。

  2. SDK

    我的插件的软件开发工具包,包含

    1. 一个 OBEX 客户端协议(OBEX 文件夹)

      提供主要功能,包括连接、断开连接和文件传输。

    2. 插件接口(IPhonePlugIn.vb
    3. 串行端口连接监控器(Monitor.vb

      自动检测此程序的手机。

    4. 插件发现和使用服务(PlugInSerivce.vb)。
  3. 插件

    其他项目都是插件。插件主要基于 SDK 提供的服务。所有插件仅用于演示,并且它们只提供从 PC 到手机的单向传输。索尼爱立信、西门子 CX6C 和摩托罗拉都基于 OBEX 协议。诺基亚 S40 基于 FBUS 协议。三星基于其自己的 AT 命令协议。

注意

  1. 诺基亚 S40 FBUS 协议仅在 PC 到手机传输方面具有核心技术;没有错误报告,也没有失败通知。如果失败,它甚至会在您的手机上创建一个死文件,并且您无法删除它!!!
  2. 所有插件的使用风险自负!!!

我将重点介绍 SDK 项目和插件。要使这些项目协同工作,请查看 FileTransferCodeDemo 项目。

插件方案

插件方案的优势

由于不同公司的手机各不相同,我们无法编写一个程序来支持所有手机。如果我们可以做到,那肯定是一个庞大的项目,并且缺乏可扩展性。我们必须找到一种方法来让生活更轻松。插件方案将满足此类需求

  1. 它很灵活。我们可以编写一个主程序,剩下的工作就是编写插件并将它们的 DLL 文件复制过去。
  2. 易于管理。当我们发现错误时,只需修改和测试单个插件,而不必触及其他插件和主程序。
  3. 易于使用。如果我只有一部手机,我只需复制一个 DLL 文件。

插件接口

插件接口是一个定义了我们在插件中将使用到的主要通用功能的接口。所有插件都将实现这个接口。稍后,我的插件服务将查找 DLL 中实现此接口的所有类。我的接口如下所示

插件服务

插件服务提供了搜索实现特定接口的 DLL 的能力。.NET 为我们提供了 System.Reflection 命名空间来进行 DLL 的反射。FindPlugins 函数查找所有 DLL,然后 ExamineAssembly() 函数使用反射来检查 DLL。CreateInstance() 函数用于创建插件的对象实例。有关详细信息,请参阅代码。我感谢作者编写了这些片段。

我编写了一个 SelectPlugin() 函数。此函数检查手机的型号 ID,然后将其与 <Plug-in>.SupportModelID() 字符串进行比较。如果匹配,该函数将返回一个插件编号以指示要使用的插件。

检查手机型号 ID 很简单。您可以简单地向串行端口发送一个称为“AT+CGMM”的 AT 命令,然后比较返回的字符串。

使用我的插件代码

这是一个演示使用我的插件方案的代码片段

Dim ap As PluginServices.AvailablePlugin()
ap = PluginServices.FindPlugins(Application.StartupPath, _
     "Dreamworld.FileTransfer.SDK.IPhonePlugIn")
Dim pluginToUse As Integer = _
  PluginServices.SelectPlugin(phoneID, ap)
Dim phone As IPhonePlugIn = _
  CType(PluginServices.CreateInstance(ap(pluginToUse)), _
  IPhonePlugIn)

基本串行端口操作

在这里,我只向您展示一些我在代码中使用的基本串行端口操作。有关更多串行端口示例,请参阅 MSDN 文档。

首先,您必须将 System.IO.Ports 命名空间导入到您的项目中。然后创建一个新的 SerialPort 实例;在这里,我们称之为 mPort

然后您必须对串行端口进行一些设置。

'Replace x with your COM port number
mPort.PortName = "COMx"
'Speed of your link. If you get 
'bad data, please slow down this.
mPort.BaudRate = 115200
'Data Terminal Ready signal. 
'It's better to set this enable.
mPort.DtrEnable = True
'Data Ready to Send signal. 
'It's better to set this enable.
mPort.RtsEnable = True
'Optional, If you want to send AT commands.
mPort.NewLine = Chr(13)
'Open the port
mPort.Open()

此时,您可以简单地使用 mPort.Write()mPort.Read() 来发送和接收二进制数据。要发送 AT 命令,您可以使用 mPort.WriteLine()mPort.ReadLine()

这是一个发送和接收 AT 命令的简单函数。

Function SendAT(ByVal cmd As String) As String
    mPort.NewLine = Chr(13)
    mPort.WriteLine(cmd)
    mATTimeOut = 1000

    Dim response As New Text.StringBuilder
    Dim start As Date = Now
    Do
        Thread.Sleep(10)
        Dim rsp As String = mPort.ReadExisting()
        response.Append(rsp)
        If Now.Subtract(start).TotalMilliseconds > _
                               mATTimeOut Then
            Throw New TimeoutException("AT TimeOut")
        If response.ToString.Contains("OK") Or _
           response.ToString.Contains("ERROR") Then
              Exit Do
    Loop
     Return response.ToString
End Function

有关更多详细信息,请参阅我的程序以及 MSDN 文档。

监控和分析数据传输的工具

我发现了一个名为 **HHD Serial Monitor** 的非常强大的工具,用于监控和分析数据传输。它可以监控您的串行端口发送和接收的数据。最新版本可以在 这里 找到。在这篇文章中,我使用了版本 3.22,因为我发现我在 4.0 版本中无法监控调制解调器。

OBEX 文件传输

什么是 OBEX

OBEX 是 Object Exchange 的缩写,它是 IrDA 或蓝牙技术的一个顶级协议。OBEX 广泛用于 PDA 和手机等移动设备。我的两部手机都支持 OBEX。对于西门子、索尼爱立信和摩托罗拉,OBEX 易于使用,但诺基亚手机通过 FBUS 使用 OBEX,这很难用。

OBEX 对象模型和头部

有关此主题的更多详细信息,请参阅 IrOBEX 协议。

OBEX 示例

这些示例来自我之前的文章。我使用串行监控器来监控数据。PC 是客户端,西门子 M55 是服务器。

注意

灰色用于解释,黄色用于实际数据。

  1. 连接,断开连接

    数据传输

  2. 将文件发送到 \Sound\1.mid,313 字节。

    西门子的最大包长度为 474 字节。所以这个文件可以填满一个包。

    简要过程:连接->切换到根目录->切换到 Sound 文件夹->Put->…

    精确过程:(忽略连接部分)

  3. 将文件发送到 \Pictures\102725.jpg,5314 字节。

    简要过程:连接->切换到根目录->切换到 \Pictures 文件夹->Put->…

    精确过程:(忽略连接部分)

如何进入和退出 OBEX 模式

现在我们知道了如何传输文件,但如何进入 OBEX 模式呢?手机制造商自己决定如何进入 OBEX 模式。

西门子

首先,您必须能够发送 AT 命令。然后发送“AT^SQWE=0”,等待响应,然后发送“AT^SQWE=3”,等待响应。然后您将进入 OBEX 模式。

提示:我也可以在西门子 M55 的手机工厂模式中看到从 GIPSY 到 OBEX 的串行状态。

要退出 OBEX 模式,请发送“+++”并等待一秒钟以上。

摩托罗拉 C650

您必须能够发送 AT 命令。然后发送“AT+MODE=22”,您就进入了 OBEX 模式。

要离开 OBEX 模式,您应该关闭端口并重新打开,然后一切都会正常。

索尼爱立信 T618/K508

您必须能够发送 AT 命令。然后发送“AT*EOBEX”,您就进入了 OBEX 模式。

使用我的 OBEX 代码

我的 Dreamworld.Protocol.OBEXClient.Command 类提供了 OBEX 的基本操作,例如连接、断开连接、列出文件夹和文件传输。您的工作是实现 EnterOBEX()ExitOBEX() 函数。有关更多详细信息和示例,请参阅我的西门子 CX6C 项目。

诺基亚 FBUS 文件传输

如上所述,FBUS 协议在互联网上没有详细文档。我知道一个名为 Gnokii 的开源项目,它在此协议上做了一些工作,但仍然不够详细。接下来该做什么?我只能监控其他软件的文件传输过程,进行分析,然后实现它。

要进入诺基亚 FBUS 协议,您必须首先将波特率设置为 115200,并将 DTR 设置为 off,RTS 设置为 off。

FBUS 基础和示例

FBUS 将每个数据段称为一个**帧**。以下是 FBUS 版本 2 的帧格式(**来自 Gnokii 文档**)

[FrameID, DestDev, SrcDev, MsgType, 0x00, FrameLength, 
      {block}, FrameToGo, SeqNo, PaddingByte?, ChkSum1, ChkSum2]
名称 描述
FrameID 0x1c: IR/FBUS
0x1e: Serial/FBUS
DestDev, SrcDev 0x00: 移动电话
0x0c, 0x10: TE (PC)
MsgType 有关详细信息,请参阅 Gnokii
FrameLength [block] + 2 的长度
FrameToGo 0x0n 表示此帧之后还有 n-1 个帧。
SeqNo [0xXY] X=4: 第一个块 X=0: 继续块 Y: 序列号
PaddingByte 如果 FrameLength 为奇数,则为 0x00,但无论如何它都不存在
ChkSum1 帧的奇数位进行 XOR
ChkSum2 帧的偶数位进行 XOR

让我们先看看从手机到 PC 的两个 FBUS 数据段

PC 请求

您会注意到,在发送第一个帧之前,发送了大量的 0x55。这些 0x55 被称为同步信号。为什么发送 0x55 而不是其他十六进制值?您知道 0x55 的二进制是 1010101,在串行线上将是 01010101。这些“0x55”会连接在一起形成重复的“01”,当手机接收到足够的“01”以确保线路正常时,手机将切换到 FBUS 模式。

我们来看看

参考系 1

这是一个请求帧,它请求手机版本信息

参考系 2

这是一个**确认帧**。TE 发送的每个帧都会返回一个 MsgID=0x7F 的确认帧。其格式为

{FrameID, DestDev, SrcDev, 0x7F, 0x00, 0x02, 
        ID_Command, ID_SeqNo, ChkSum1, ChkSum2}
  • ID_Command:您正在确认的 commandID
  • ID_SeqNo:您正在确认的序列号。

在我们的示例中,ID_Command 是 **0xD1**,这是我们请求 **0xD1** 中的 ID。

ID_SeqNo 是一个等于 (SeqNo AND 0x0F) 的数字。在这里,(0x40 AND 0x0F) = 0x00

帧 3

这是我们从手机收到的版本信息。请注意,序列号是 **0x44**。这意味着当前的序列号是 4。每次发送新帧时,序列号应为 (seq+1) MOD 8。所以帧 5 的序列号应该是 5。

帧 4

对最后一帧的确认帧。收到并检查完最后一帧后,您必须尽快返回一个确认帧。通常,您必须在大约 300ms 内响应。否则,手机将重试三次发送相同的帧。如果手机未收到确认帧,手机将断开连接。

FBUS 文件传输

我认为提供一个完整的示例来展示这一点很难,但我将展示如何做。请看我的草稿代码作为示例。

  • 步骤 1:切换到 FBUS 模式。如您所知,发送几次“0x55”。
  • 步骤 2:发送我称为初始化帧的帧到手机。有关详细信息,请参阅我的 Sub Prepare()
  • 步骤 3:发送包含手机上路径的完整文件名,并准备发送数据。请参阅 privateSendFile()
  • 步骤 4:发送数据。请参阅 privateSendFile()
  • 步骤 5:发送完整消息。

我的代码是草稿代码,所以可能难以阅读,并且会有错误,因为我没有更多关于 FBUS 的详细文档。我是通过监控其他软件来学习这些步骤的。如果您愿意,可以尝试监控 MobTime Cell Phone manager

基于三星 AT 命令的文件传输

下面列出了一些 AT 命令

AT 命令 描述
AT+FSCD="<DIR>" 切换到 <DIR>
AT+FSDI="<DIR>" 目录信息
AT+FSDL="<DIR>" 目录列表
AT+FSFW=-1, "<FILENAME>", 0, "", <LEN>, <CRC> 发送文件。
AT+FSFE=0, "<FILENAME>" 删除文件。

让我们看一个例子

请求

Change the directory to "/å?¾ç?". Don't care the folder name here.
    If your phone is English, then it will be /Picture
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D                                           ".

答案

Folder Successfully changed.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D 0D 0A 4F 4B 0D 0A                         "...OK..

请求

Repeat. I don't know why.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D                                           ".

答案

Repeat. I don't know why.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D 0D 0A 4F 4B 0D 0A                         "...OK..

请求

Write a file. 18752 is the length.
   880445898 is unsigned CRC32 code for the file.
41 54 2B 46 53 46 57 3D 2D 31 2C 20 22 E6 B5 8B AT+FSFW=-1, "æµ?
E8 AF 95 2E 6A 70 67 22 2C 20 30 2C 20 22 22 2C è¯.jpg", 0, "",
31 38 37 35 32 2C 38 38 30 34 34 35 38 39 38 0D 18752,880445898.

答案

OK. You can continue. "##>" indicates continue your transfer.
41 54 2B 46 53 46 57 3D 2D 31 2C 20 22 E6 B5 8B AT+FSFW=-1, "æµ?
E8 AF 95 2E 6A 70 67 22 2C 20 30 2C 20 22 22 2C è¯.jpg", 0, "",
31 38 37 35 32 2C 38 38 30 34 34 35 38 39 38 0D 18752,880445898.
23 23 3E 0D 0A                                  ##>.. 

请求

Send data. Maximum data length is 512 bytes.
FF D8 FF E0 00 10 4A 46 49 46 00 01 02 00 00 01 ÿØÿà..JFIF......
......
<Total 512 bytes data here>

答案

Please continue.
0D 0A 23 23 3E 0D 0A                            ..##>..

请求

...
<Continue data segment>

答案

...

请求

Send last segment of data. Phone will calculate
   total data you send. When phone received 
   18752 bytes, it will return OK
   
91 56 53 E9 BF 5B 55 68 AF 8E 35 66 87 06 3D 35 VSé¿[Uh¯?5f.=5
<.......>
E3 C6 63 31 E3 C6 63 31 E3 C6 63 31 E3 C7 FF D9 ãÆc1ãÆc1ãÆc1ãÇÿÙ

答案

Phone has received all your data.
0D 0A 4F 4B 0D 0A ..OK.. 

整个过程就是这样,简单易懂。试试编程吧!

摘要

现在是休息或喝杯咖啡的时候了。我认为文件传输不应该像您想象的那么神秘。

OBEX 协议被广泛使用且功能强大,但不如 FBUS 那么微小。FBUS 难以使用,并且缺乏详细文档。另一方面,三星的 AT 命令非常清晰易用。

要制作一个真正稳定的文件传输工具还有很长的路要走;我还在学习,您也是。让我们分享我们的失败和成功。如果您在阅读我的文章时遇到问题,请与我联系。

互联网链接

移动电话文件传输的简单指南 - CodeProject - 代码之家
© . All rights reserved.