blacksenator/fritzsoap

通过SOAP接口读取/写入FRITZ!Box数据

v2.8.5 2023-05-17 20:26 UTC

README

首先!由于版本2.x中的类结构发生了变化,因此需要创建新的类实例及其SOAP客户端(参见使用)。

目的

此类提供通过FRITZ!Box路由器和FRITZ!Repeater上的TR-064和UPnP(IGD)接口读取和操作数据的函数,这些路由器和中继器由AVM提供。例如,FRITZ!Box 7590提供超过500个接口(动作)在超过50个服务中。

为了参考,强烈建议咨询AVM提供的接口信息!尽管动作数量众多,但并非所有通过FRITZ!OS GUI显示或参数化的内容都可以通过这些接口查询或修改(参见愿望)。创建此库是为了尽可能简化大量接口的使用。

摘录

只需稍加注意即可执行所需的SOAP操作。只需调用其专用类的实例化即可获取相应的SOAP客户端,并自动获得正确的位置(serviceType)和uri(locationURL)。因此,您只需知道需要什么动作以及它在哪个服务中提供。那么您就知道需要实例化哪个以及函数的命名方式 - 仅此而已!

例如,您想获取当前呼叫者列表:在这种情况下,所需的动作 GetCallListx_contact 服务提供。因此,编码相当简单,如下所示

$fritzbox = new x_contact($url, $user, $password);
$callList = $fritzbox->getCallList();

这就完了!简单、方便、直接!

文件fritzsoap.php是提供一般基本对象的元类。所有其他文件都是这个元类的子类。直接实例化fritzsoap会导致错误。

类和方法

每个子类恰好对应一个服务!命名是相同的。在特定类中,每个动作都有一个函数!函数名称与动作名称匹配 - 遵循通用PHP语言规则:无连字符和PSR-1:camelCase。例如,X_AVM-DE_GetIPTVOptimized 动作通过x_AVM_DE_GetIPTVOptimized 函数调用。

根据PSR,类名称应该是StudlyCaps。由于面向对象以及因此动态确定针对特定服务的专用类,因此必须故意避免这一点。

其他函数

在某些情况下,相应的类包含一些其他有用的函数,这些函数可以更容易地调用接口。这些额外编码的函数随后列在标题中,其编码可在相应文件的末尾找到。

此外,父类fritzsoap.php继承了一些其他函数

  • public
    • getClient()
    • getServiceDescription()
    • getURL()
    • getServerAddress()
  • protected
    • getFritzBoxServices()
    • errorHandling()
    • boolToState()
    • arrayToXML()

函数的使用说明在各自的标题中。

有用的依赖关系

此外,该仓库使用fbvalidateurl(由Composer自动安装)。因此,您无需担心是否输入了带有或不带有方案的路由地址(http:///https://),是否带有主机名(fritz.box)或IP(192.168.178.1)。基于验证的URL,将自动确定正确的SOAP端口

刷新SID

请注意,如果程序运行时间较长,可能需要通过调用getClient()函数来刷新SID!那么,长时间是什么意思?AVM文档在这里也不够精确:“...一旦分配,会话ID有效期为20分钟。只要对FRITZ!Box的访问是活跃的,有效性就会自动延长...”以及在同一文档中:“...可以通过删除会话ID在任何时候结束会话,即使在自动的10分钟超时启动之前...

起源

由于提供的服务和动作数量众多,手动编码所有这些是不可能的!因此,所有子类最初都是由程序生成的!这种生成的依据是我FRITZ!Box 7590的服务描述文件(XML)。所有设备都通过SOAP端口(例如//fritz.box:49000/tr64desc.xml)提供这些描述文件。读取那里的信息,并从中生成代码是转换大量服务、它们的动作和参数到通用类结构的最简单和最完美的方式。

如果您想了解更多关于此信息,请仔细查看fritzsoap.php。生成的程序基于一个特定的子类,这个子类**不**是库的一部分,因为在本地上重复生成类没有意义。

缺失的服务/动作

如果您通过getServiceDescription(true)收到了预期之外的、未包含在此处的服务,请简单地将生成的XML(每个文件头部都有电子邮件地址)发送给我,我将根据它生成缺失的类(不言而喻,无需担心隐私,因为XML不包含任何私人数据或凭据)。

如果您的FRITZ!Box提供了超过三个WLAN接入点,那么您可能缺少wlanconfig4服务。

重复项

  • WAN*服务(大写!)指的是IGD1 resp. IGD2描述,因此出现两次:作为WAN*1_1.phpWAN*1_2.php
  • wlanconfig*是根据提供的接入点数量找到的(2400 GHz、5000 GHz、guest、...)
  • Control_*见下文

完成

大多数动作都已审查,编码已准备好使用。在其他所有情况下,您将在类头部注释中找到免责声明:THIS FILE IS AUTOMATIC ASSEMBLED BUT PARTLY REVIEWED!或如果此类仍然通用且尚未审查,则为THIS FILE IS AUTOMATIC ASSEMBLED!

如果尚未审查您所需动作的编码,现有示例应显示完成该函数代码以供您所需动作使用是多么简单(**高度欢迎对此类扩展的贡献**)。在大约一半的情况下(如果没有输入参数),只需适应可能错误的消息就足够了,因为动作主要提供返回值数组,这些数组可以被调用程序进一步处理。

您可以通过查看注释来了解函数编码是否经过检查。在其他所有情况下,未经检查的函数看起来就像以下未审查的函数示例(来自 x_homeauto.php

/**
 * setSwitch
 *
 * automatically generated; complete coding if necessary!
 *
 * in: NewAIN (string)
 * in: NewSwitchState (string)
 *
 * @param string $aIN
 * @param string $switchState
 * @return void
 */
public function setSwitch($aIN, $switchState)
{
    $result = $this->client->SetSwitch(
        new \SoapParam($aIN, 'NewAIN'),
        new \SoapParam($switchState, 'NewSwitchState'));
    $this->errorHandling($result, 'Could not ... from/to FRITZ!Box');
}

您可以在注释部分和函数编码中找到输入或输出参数(参数),如果有的话。为了方便完成这个创建,请仔细查看已完成的函数。

但正如我之前说的

  • 强烈建议您查阅AVM提供的接口信息AVM接口信息
  • 对贡献非常欢迎。分享您的改进!有了您的PR,每个人都能从进一步的完善中受益!

幽灵

服务

自动生成还产生了未被或未明确由AVM记录的服务。因此,这些类在类注释中没有指向参考文档的链接!

这些可能指的是来自开放连接基金会(即UPnP-论坛)的规范。但解析这些或手动跟踪它们远远超出了我的能力。

在其他所有情况下,您将找到类似这样的链接

 * @see: https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/*.pdf
AURA(AVM USB远程访问)

到目前为止有一个例外:AURA。通过在IP电话论坛的一个帖子中,我了解了这个服务的工作方式。该服务的六个操作已经编码,可以在/docs文件夹中找到非官方文档。您必须已激活FRITZ!Box中的USB远程访问功能,才能访问此服务!

一些其他的幽灵
  • any没有操作 - aura的通用模板?
  • avmnexus
  • fritzbox在FRITZ!OS 7.29(或之前)中消失,但在7.50中再次出现
  • l2tpv3
控制

在FRITZ!OS 7.29及以下版本中,存在一组同名Control服务,我找到了七个具有不同的serviceType和controlURL的服务。因此,这些服务相应地在类中映射,从Control_1Control_7。由于FRITZ!OS 7.50不再包含在描述文件中,我保留它们以保持完整性。

操作

在某些情况下,在*SCPD.xml中定义的操作未记录且/或不存在。在后一种情况下,结果是SOAP错误403(不可用操作)。以下注释中确定的这一点可以在函数的标题中找到

     * ACTION IS NOT IN THE FILE ABOVE DOCUMENTED!

要求

安装

您可以通过Composer进行安装

"require": {
    "blacksenator/fritzsoap": "^2.8"
},

git clone https://github.com/blacksenator/fritzsoap.git

用法

身份验证

有几个服务(与IGD相关)可以在没有任何(*)凭证的情况下调用

  • WANCommonIFC1
  • WANDSLLinkC1
  • WANIPConn1
  • WANIPv6Firewall1

以及上述提到的附加公共函数 (*),因为使用了fbvalidator,默认使用fritz.box作为地址

所有其他服务都需要指定FRITZ!Box URL、用户名和密码。

示例

以下是提供的一些动作或附加函数的调用示例

如果您想获取包含FRITZ!Box或FRITZ!Repeater所有可用服务的文件

require_once('vendor/autoload.php');

use blacksenator\fritzsoap\x_contact;

$fritzbox = new x_contact;  // no credentials needed in this particular case!
$services = $fritzbox->getServiceDescription();
$services->asXML('services.xml');

提示:由于继承,所有类中都存在 getServiceDescription() 函数,并且无需任何凭证即可使用,它提供了一个很好的概述!您还可以通过 getServiceDescription(true) 获取更详细的结构。在这种情况下,所有操作的参数都将输出,以及信息来源的 XML 文件的文件名。

示例输出(截图):alt text

但现在有一些更实用的应用:获取所有网络设备列表的示例

$fritzbox = new hosts($url, $user, $password);
$meshList = $fritzbox->getMeshList();

拨打电话的示例(连接到您的电话设备之一:点击拨打)

$fritzbox = new x_voip($url, $user, $password);
$fritzbox->x_AVM_DE_DialNumber('030399760');

此外,还可以拨号与 FRITZ!Box 拨号一样的东西:内部电话号码、控制通话的键盘代码等。无法传输 AT 命令,也无法处理来电。请记住,如果您想使用 x_AVM_DE_DialNumber()x_AVM_DE_HangUp(),则需要激活“点击拨打”(Wahlhilfe)。您甚至可以使用 x_AVM_DE_DialGetConfig()x_AVM_DE_DialSetConfig() 通过程序获取状态和(取消)激活此功能。因此,请更详细地查看 x_voip.php,其中包含有用的函数,例如 x_AVM_DE_GetPhonePort()(例如 getPhonePorts())。

异常处理

默认情况下,在 fritzsoap.php 及其子类中,SOAP 参数 exceptions 设置为 false

SOAP_EXCEPTIONS = false,
...
'exceptions' => self::SOAP_EXCEPTIONS,

因此,SOAP 错误不会抛出异常!每个函数调用都链接了一个更方便的例程,并且如果发生错误,则 $result 变量不携带请求的值,而是携带 SoapFault 信息,它输出由 AVM 定义的错误及其编号和描述,这些信息也可以在特定服务的相关文档中找到。

在某些情况下,不使用此实现例程可能是有意义的

if ($this->errorHandling($result, 'Could not ... from/to FRITZ!Box')) {

而是自行 查询

if (is_soap_fault($result)) {

错误处理

如果调用类或其函数导致错误,可能的原因包括

  • 必要的 php 模块 未安装
  • 您的 FRITZ!Box/FRITZ!Repeater 不提供该服务(功能范围取决于 FRITZ!Box 模型?)
  • 您的设置
    • 在 FRITZ!Box 中未激活某些功能(例如 UPnP 或 USB 远程访问)
    • FRITZ!Box 用户没有适当的权限(例如 TR-064 访问)

愿望

首先,必须说 TR-064 接口是一件好事。虽然大约有 500 个操作给人一种几乎可以通过 SOAP 输出或更改 FRITZ!Box 几乎所有内容的印象,但这当然是不正确的!在我看来,缺少一些有趣输出和任务的函数(操作)。仅举几个例子

  • 电话
    • 断开/拒绝来电
  • 家长控制
    • 获取带有其配置文件的连接设备
    • 更改设备的过滤器/配置文件
    • 以数组形式获取状态为的工单列表
  • USB 设备
    • 获取连接的存储设备
    • 断开/重新连接这些设备

除此之外,还有一些操作,不清楚要传递哪个值作为输入,或者没有提供输入参数的操作。最后但并非最不重要的是,有些情况下 get 操作返回一个值(例如 NewDeviceHandle),显然下一个操作 getDeviceByHandle() 需要作为输入,但实际上并不接受。

免责声明

FRITZ!Box、FRITZ!Repeater、FRITZ!OS是AVM的商标。AVM与此软件无任何关联,仅使用他们发布的接口

许可协议

本脚本遵循MIT许可协议发布。

作者

版权所有 (c) 2019 - 2023 Volker Püschel