6

我正在尝试实现 SMAPI 服务,但遇到了一些问题。

我构建了一个“假”服务,它为这些端点提供硬编码的响应:

  • 获取媒体URI
  • 获取最后更新
  • 获取媒体元数据
  • 获取元数据
  • 获取扩展元数据
  • 获取会话 ID

我已按照说明添加自定义服务,保持所有功能未选中

我看到我的 Sonos iPhone 应用程序中列出了我的新测试服务,但是当我选择它时,我看到一个屏幕显示“无法浏览音乐”。

我不确定如何调试正在发生的事情,所以感觉就像我在黑暗中刺伤。我不想投机地做出可能与问题无关的更改 - 这似乎是浪费大量精力的秘诀。

有没有办法查看 Sonos Controller 应用程序(客户端)出现的错误?我查看了http://[device ip]:1400/support/aggregate日志,但没有看到任何提及我的服务的域名,也没有看到任何似乎相关的内容。

我知道(至少有一些)请求正在影响我的服务,特别是调用getLastUpdateand getMetadata。这是日志的输出:

2016-02-23T18:55:24.316373+00:00 app[web.1]: Started POST "/soap/action" for 213.86.218.202 at 2016-02-23 18:55:24 +0000
2016-02-23T18:55:24.316485+00:00 app[web.1]: Started POST "/soap/action" for 213.86.218.202 at 2016-02-23 18:55:24 +0000
2016-02-23T18:55:24.431603+00:00 app[web.1]: Processing by SoapController#get_last_update as HTML
2016-02-23T18:55:24.431611+00:00 app[web.1]: Processing by SoapController#get_last_update as HTML
2016-02-23T18:55:24.438452+00:00 app[web.1]: params.inspect: {}
2016-02-23T18:55:24.438458+00:00 app[web.1]: params.inspect: {}
2016-02-23T18:55:24.447855+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/gems/wash_out-0.10.0/app/views/wash_out/document/response.builder (7.6ms)
2016-02-23T18:55:24.447907+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/gems/wash_out-0.10.0/app/views/wash_out/document/response.builder (7.6ms)
2016-02-23T18:55:24.448279+00:00 app[web.1]: Completed 200 OK in 17ms (Views: 9.5ms | ActiveRecord: 0.0ms)
2016-02-23T18:55:24.457801+00:00 app[web.1]: Started POST "/soap/action" for 213.86.218.202 at 2016-02-23 18:55:24 +0000
2016-02-23T18:55:24.448327+00:00 app[web.1]: Completed 200 OK in 17ms (Views: 9.5ms | ActiveRecord: 0.0ms)
2016-02-23T18:55:24.464365+00:00 app[web.1]: Processing by SoapController#get_metadata as HTML
2016-02-23T18:55:24.457861+00:00 app[web.1]: Started POST "/soap/action" for 213.86.218.202 at 2016-02-23 18:55:24 +0000
2016-02-23T18:55:24.464428+00:00 app[web.1]: Processing by SoapController#get_metadata as HTML
2016-02-23T18:55:24.465101+00:00 app[web.1]: params.inspect: {"id"=>"root", "index"=>0, "count"=>100}
2016-02-23T18:55:24.465154+00:00 app[web.1]: params.inspect: {"id"=>"root", "index"=>0, "count"=>100}
2016-02-23T18:55:24.472056+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/gems/wash_out-0.10.0/app/views/wash_out/document/response.builder (3.4ms)
2016-02-23T18:55:24.472049+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/gems/wash_out-0.10.0/app/views/wash_out/document/response.builder (3.4ms)
2016-02-23T18:55:24.472248+00:00 app[web.1]: Completed 200 OK in 8ms (Views: 6.9ms | ActiveRecord: 0.0ms)
2016-02-23T18:55:24.472251+00:00 app[web.1]: Completed 200 OK in 8ms (Views: 6.9ms | ActiveRecord: 0.0ms)

任何帮助将不胜感激!

更新 这是使用 SoapUI 对我的假服务发出请求的输出:

  1. getLastUpdate

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getLastUpdateResponse>
             <getLastUpdateResult>
                <catalog>Catalog last updated 2016-02-18 11:52:30</catalog>
                <favorites>User: Rob last updated favorites 2016-02-18 12:01:00</favorites>
                <pollInterval>30</pollInterval>
             </getLastUpdateResult>
          </tns:getLastUpdateResponse>
       </soap:Body>
    </soap:Envelope>
    
  2. getSessionId

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getSessionIdResponse>
             <getSessionIdResult>user0001</getSessionIdResult>
          </tns:getSessionIdResponse>
       </soap:Body>
    </soap:Envelope>
    
  3. getMetadata

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getMetadataResponse>
             <getMetadataResult>
                <index>0</index>
                <count>2</count>
                <total>2</total>
                <mediaMetadata>
                   <id>some_id_1</id>
                   <title>Title 1</title>
                   <mimeType>audio/mp4</mimeType>
                   <itemType>track</itemType>
                   <displayType>List</displayType>
                   <summary>Summary text 1. Summary text 1. Summary text 1.</summary>
                   <trackMetadata>
                      <artistId/>
                      <artist/>
                      <composerId/>
                      <composer/>
                      <albumId/>
                      <album/>
                      <albumArtURI/>
                      <albumArtistId/>
                      <albumArtist/>
                      <genreId/>
                      <genre/>
                      <duration/>
                      <canPlay/>
                      <canSkip/>
                      <canAddToFavorites/>
                      <rating/>
                      <trackNumber/>
                   </trackMetadata>
                   <streamMetadata></streamMetadata>
                </mediaMetadata>
                <mediaMetadata>
                   <id>some_id_2</id>
                   <title>Title 2</title>
                   <mimeType>audio/mp4</mimeType>
                   <itemType>track</itemType>
                   <displayType>List</displayType>
                   <summary>Summary text 2. Summary text 2. Summary text 2.</summary>
                   <trackMetadata>
                      <artistId/>
                      <artist/>
                      <composerId/>
                      <composer/>
                      <albumId/>
                      <album/>
                      <albumArtURI/>
                      <albumArtistId/>
                      <albumArtist/>
                      <genreId/>
                      <genre/>
                      <duration/>
                      <canPlay/>
                      <canSkip/>
                      <canAddToFavorites/>
                      <rating/>
                      <trackNumber/>
                   </trackMetadata>
                   <streamMetadata></streamMetadata>
                </mediaMetadata>
             </getMetadataResult>
          </tns:getMetadataResponse>
       </soap:Body>
    </soap:Envelope>
    
  4. getExtendedMetadata

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getExtendedMetadataResponse>
             <getExtendedMetadataResult>
                <mediaMetadata>
                   <id>some_id_1</id>
                   <title>Title 1</title>
                   <mimeType>audio/mp4</mimeType>
                   <itemType>track</itemType>
                   <displayType>List</displayType>
                   <summary>Summary text 1. Summary text 1. Summary text 1.</summary>
                   <trackMetadata>
                      <artistId/>
                      <artist/>
                      <composerId/>
                      <composer/>
                      <albumId/>
                      <album/>
                      <albumArtURI/>
                      <albumArtistId/>
                      <albumArtist/>
                      <genreId/>
                      <genre/>
                      <duration/>
                      <canPlay/>
                      <canSkip/>
                      <canAddToFavorites/>
                      <rating/>
                      <trackNumber/>
                   </trackMetadata>
                   <streamMetadata></streamMetadata>
                </mediaMetadata>
             </getExtendedMetadataResult>
          </tns:getExtendedMetadataResponse>
       </soap:Body>
    </soap:Envelope>
    
  5. getMediaMetadata

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getMediaMetadataResponse>
             <getMediaMetadataResult>
                <id/>
                <title>Fake Track Title</title>
                <mimeType>audio/mp4</mimeType>
                <itemType>track</itemType>
                <displayType/>
                <summary/>
                <trackMetadata>
                   <artistId>artist:12345</artistId>
                   <artist>Bach</artist>
                   <composerId/>
                   <composer/>
                   <albumId/>
                   <album/>
                   <albumArtURI>https://sonos.therocketfuel.com/images/istockphoto_1945235_satisfaction.jpg</albumArtURI>
                   <albumArtistId/>
                   <albumArtist/>
                   <genreId/>
                   <genre>Classical</genre>
                   <duration>459</duration>
                   <canPlay>true</canPlay>
                   <canSkip>true</canSkip>
                   <canAddToFavorites>false</canAddToFavorites>
                   <rating/>
                   <trackNumber/>
                </trackMetadata>
                <streamMetadata></streamMetadata>
             </getMediaMetadataResult>
          </tns:getMediaMetadataResponse>
       </soap:Body>
    </soap:Envelope>
    
  6. getMediaURI

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.sonos.com/Services/1.1">
       <soap:Body>
          <tns:getMediaURIResponse>
             <getMediaURIResult>https://sonos.therocketfuel.com/audio/960bpm.m4a</getMediaURIResult>
          </tns:getMediaURIResponse>
       </soap:Body>
    </soap:Envelope>
    
4

2 回答 2

1

解决方案

我终于弄明白了,基本上我的服务返回了有效的 XML,但这对于 WSDL 模式是不正确的。

我使用SoapUI进行了调试,如下所示:

  1. 创建一个新的 SOAP 项目

    • 项目名称:随便你
    • 初始 WSDL:指向您的服务提供 WSDL 的位置
    • 检查“创建请求”和“创建测试套件”
  2. Ctrl-单击(右键单击)TestSteps 文件夹并单击“添加步骤”,然后选择“SOAP 请求”

  3. 给它起任何你喜欢的名字(我用过例如actionName_validate)

  4. 选择您要验证的 SOAP 操作/操作

  5. 确保勾选“添加架构断言(添加响应符合其架构的验证)”复选框,然后单击确定

  6. 从左侧列表中双击您新创建的测试步骤并运行它(单击左上角的绿色播放按钮)

  7. 如果您的服务响应符合 WSDL,您会在左下角看到一个绿色圆圈,上面写着“断言”。如果没有,它会是红色的,它会给你一个完整的列表,列出你的回答有什么问题。

  8. 一个一个地修复你的架构的任何问题,直到它变成绿色

如果您使用 Ruby,请提供更多详细信息

此外,这里有一些更多的细节可能会在这种情况下对某人有所帮助,特别是如果你正在用 Ruby 构建你的服务......

Ruby 中围绕 SOAP 服务的工具不如 Java(甚至 PHP)。我使用的是wash_out gem,它虽然对全新的SOAP 服务很有用,但表达能力不足以让您定义与官方Sonos WSDL 匹配的类型映射等。我也无法让它生成正确的 XML 响应(它错过了xmlns所需的关键属性,或者不会命名所有元素。)

我通过手动提供带有模板的 XML 响应来解决这个问题,因为起初这是最简单的方法。您可以使用.xml.erb模板,也可以将 xmlbuilder语法与.xml.builder模板一起使用。但实际上,您可以以任何您想要的方式生成 XML,例如to_xml或其他一些演示者类型库。

对于 WSDL,我改用了官方的 Sonos SMAPI WSDL,只是将底部的服务地址更改为指向我的服务提供此修改后的 WSDL 的位置。

于 2016-02-25T13:14:19.967 回答
0

您是否尝试过使用 SoapUI,添加您的端点并直接点击它以查看您得到了什么?

于 2016-02-23T22:45:43.920 回答