Websocket点歌API-精简指令集
<p>[toc]</p>
<h1>简要描述</h1>
<ul>
<li>Websocket通讯点歌API(设备端和服务端通讯协议)</li>
</ul>
<h1>请求URL</h1>
<ul>
<li><code>Websocket【ws.xxxxx.com:port】</code></li>
</ul>
<h1>请求方式</h1>
<ul>
<li>Websocket通讯</li>
</ul>
<h1>1. 通讯示例</h1>
<h2>1.1 json发送示例(设备 -》服务器)</h2>
<pre><code class="language-json">{
&quot;msgtype”:”register&quot;,
&quot;mac&quot;: &quot;a1:b2:c3:d4:e5:f6&quot;,
&quot;sn&quot;: xx
}</code></pre>
<ul>
<li>数据说明</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">消息类型</td>
</tr>
<tr>
<td style="text-align: left;">mac</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">机器的唯一ID(可以使用序列号替代)</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">整型</td>
<td style="text-align: left;">sn序号, 通讯消息识别使用(每次累加1),无需验证的情况下可以忽略</td>
</tr>
</tbody>
</table>
<h2>1.2 接收示例(服务器 -》设备)</h2>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;register&quot;,
&quot;sn&quot;: 1,
&quot;result&quot;: x
}</code></pre>
<ul>
<li>数据说明</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">消息类型</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">整型</td>
<td style="text-align: left;">sn序号, 通讯消息识别使用(每次累加1),无需验证的情况下可以忽略</td>
</tr>
<tr>
<td style="text-align: left;">result</td>
<td style="text-align: left;">整型</td>
<td style="text-align: left;">返回结果码</td>
</tr>
</tbody>
</table>
<h2>1.3 结果码说明</h2>
<table>
<thead>
<tr>
<th style="text-align: left;">结果码</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">0</td>
<td style="text-align: left;">成功</td>
</tr>
<tr>
<td style="text-align: left;">10000</td>
<td style="text-align: left;"> MAC地址非法</td>
</tr>
<tr>
<td style="text-align: left;">10001 </td>
<td style="text-align: left;"> 无效参数</td>
</tr>
</tbody>
</table>
<h1>2. 通讯指令</h1>
<h2>2.1 设备上线</h2>
<p>设备->服务器</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;register&quot;,
&quot;mac&quot;:&quot;A0:B1:C2:D3:C4:E5:D6&quot;,
&quot;mv_support&quot;: 1,
&quot;sn&quot;: 1,
&quot;songver&quot;:&quot;1.x&quot;
}</code></pre>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">设备上线注册(设备上线第一条指令)</td>
</tr>
<tr>
<td style="text-align: left;">mac</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">机器唯一ID, 可以是序列号之类的</td>
</tr>
<tr>
<td style="text-align: left;">mv_support</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">照片MV是否支持(带参数则支持MV, 不带这个参数则mv不支持[默认原先出去的设备没有这个参数])</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">序列号</td>
</tr>
<tr>
<td style="text-align: left;">songver</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌库版本</td>
</tr>
</tbody>
</table>
<p>response: </p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;register&quot;,
&quot;sn&quot;:1,
&quot;result&quot;:0,
}</code></pre>
<ul>
<li>设备开机后,发起到服务器***.com的WEBSOCKET连接。</li>
<li>Websocket连接成功后,发送注册信息到服务器</li>
<li>服务器校验设备的MAC地址信息,合法返回成功,不合法返回失败</li>
<li>失败,如则进入2分钟一次的尝试注册状态</li>
</ul>
<h2>2.2 包房开启(获取房号)</h2>
<p>a)当设备检测到包房开启时,上报此动作,如果包房还在开启中,则将现有包房的id往服务器发送
b)服务器新增一个包房信息到数据库表中,返回一个vroomid到设备
c)vroomid将在扫码的时候提供有效的房间信息给用户
d)如果未获取到vroomid,后续包房功能不可使用</p>
<p>方向 设备->服务器(send):</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;vroominit&quot;,
&quot;sn&quot;:xx,
&quot;roomid&quot;: &quot;xxxxxxxxxxxxxxxxxxxx&quot;
}</code></pre>
<p>Response:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;vroominit&quot;,
&quot;sn&quot;:xx,
&quot;result&quot;:x.
&quot;roomid&quot;: &quot;xxxxxxxxxxxxxxxxxxxx&quot;
}</code></pre>
<h2>2.3.包房关闭(关闭之前的房号)</h2>
<p>a)当设备检测到包房关闭时,上报此动作
b)服务器根据vroomid更新包房信息,将包房状态设置为关闭</p>
<p>方向 设备->服务器(send)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;vroomclose&quot;,
&quot;sn&quot;:xx,
}</code></pre>
<p>Response:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;vroomclose&quot;,
&quot;sn&quot;:xx,
&quot;result&quot;:x
}</code></pre>
<h2>2.4.包房歌曲(已点)列表同步 (歌曲列表有变更的时候发送给后台)</h2>
<p>a)设备将当前的所有歌曲列表同步一次
b)服务器接收到后,将包房歌曲列表重新更新</p>
<p>方向 设备->服务器(send)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;selectedlistsync&quot;,
&quot;sn&quot;: 1,
&quot;selected_song_list&quot;: [{
&quot;songid&quot;: &quot;1111&quot;,
&quot;ID&quot;: 10,
&quot;localexist&quot;: 1
}, {
&quot;songid&quot;: &quot;1111&quot;,
&quot;ID&quot;: 10,
&quot;localexist&quot;: 1
}]
}</code></pre>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">已点列表同步</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">sn序列号</td>
</tr>
<tr>
<td style="text-align: left;">selected_song_list</td>
<td style="text-align: left;">array</td>
<td style="text-align: left;">已点歌曲数组</td>
</tr>
<tr>
<td style="text-align: left;">selected_song_list.songid</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌号</td>
</tr>
<tr>
<td style="text-align: left;">selected_song_list.ID</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">列表ID(歌曲列表中的唯一ID, 点歌机每次点播累加), 区分同歌号歌曲使用</td>
</tr>
<tr>
<td style="text-align: left;">selected_song_list.localexist</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">本地是否存在,表示是否云端或本地歌曲</td>
</tr>
</tbody>
</table>
<p>Response:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;selectedlistsync&quot;,
&quot;sn&quot;: 1,
&quot;number&quot;: 20,
&quot;result&quot;: 0
}</code></pre>
<ul>
<li>number: 返回所有歌曲总数</li>
</ul>
<h2>2.5.包房歌曲(已唱)列表同步</h2>
<p>a)包房开启时,所有已唱歌曲列表同步一次。
b)服务器接收到后,将包房歌曲列表重新更新</p>
<ul>
<li>方向 设备->服务器</li>
</ul>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;sunglistsync&quot;,
&quot;sn&quot;: 1,
&quot;sung_song_list&quot;: [{
&quot;songid&quot;: &quot;111111&quot;,
&quot;ID&quot;: 10,
&quot;isrecorded&quot;: 1,
&quot;score&quot;: 100
},
{
&quot;songid&quot;: &quot;222222&quot;,
&quot;ID&quot;: 11,
&quot;isrecorded&quot;: 0,
&quot;score&quot;: -1,
&quot;rec_id&quot;: &quot;3242422&quot;
}
]
}</code></pre>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">sunglistsync 已唱歌曲</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">sn序列号</td>
</tr>
<tr>
<td style="text-align: left;">sung_song_list</td>
<td style="text-align: left;">array</td>
<td style="text-align: left;">已点数据列表</td>
</tr>
<tr>
<td style="text-align: left;">sung_song_list.songid</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌号(歌曲唯一ID)</td>
</tr>
<tr>
<td style="text-align: left;">sung_song_list.ID</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌曲位置ID, 用于区分同一歌号不同数据位置</td>
</tr>
<tr>
<td style="text-align: left;">sung_song_list.isrecorded</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">是否录音0-未录音, 1-录音</td>
</tr>
<tr>
<td style="text-align: left;">sung_song_list.score</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">-1 无评分时候, 0-100 有评分的时分数值</td>
</tr>
</tbody>
</table>
<ul>
<li>Response:</li>
</ul>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;sunglistsync&quot;,
&quot;sn&quot;:xx,
&quot;number&quot;:xx,
&quot;result&quot;:x
}</code></pre>
<ul>
<li>number : 返回所有已唱歌曲总数</li>
</ul>
<h2>2.6 服务器遥控指令</h2>
<p>a)服务器发送一个遥控器指令到设备上
b)设备接收到该指令后直接返回成功</p>
<p>方向 服务器->设备(send)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;remotectl&quot;,
&quot;sn&quot;:1,
&quot;action&quot;:1
}</code></pre>
<p>action对应功能:</p>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">1</td>
<td style="text-align: left;">切歌(下一曲)</td>
</tr>
<tr>
<td style="text-align: left;">2</td>
<td style="text-align: left;">播放/暂停</td>
</tr>
<tr>
<td style="text-align: left;">3</td>
<td style="text-align: left;">音量+ (音乐音量+)</td>
</tr>
<tr>
<td style="text-align: left;">4</td>
<td style="text-align: left;">音量- (音乐音量-)</td>
</tr>
<tr>
<td style="text-align: left;">5</td>
<td style="text-align: left;">静音/取消静音</td>
</tr>
<tr>
<td style="text-align: left;">6</td>
<td style="text-align: left;">原唱/伴唱</td>
</tr>
<tr>
<td style="text-align: left;">7</td>
<td style="text-align: left;">MIC+ (话筒音量+)</td>
</tr>
<tr>
<td style="text-align: left;">8</td>
<td style="text-align: left;">MIC- (话筒音量-)</td>
</tr>
<tr>
<td style="text-align: left;">9</td>
<td style="text-align: left;">录音</td>
</tr>
<tr>
<td style="text-align: left;">10</td>
<td style="text-align: left;">重唱</td>
</tr>
<tr>
<td style="text-align: left;">11</td>
<td style="text-align: left;">降调</td>
</tr>
<tr>
<td style="text-align: left;">12</td>
<td style="text-align: left;">原调</td>
</tr>
<tr>
<td style="text-align: left;">13</td>
<td style="text-align: left;">升调</td>
</tr>
<tr>
<td style="text-align: left;">14</td>
<td style="text-align: left;">上(方向)</td>
</tr>
<tr>
<td style="text-align: left;">15</td>
<td style="text-align: left;">下(方向)</td>
</tr>
<tr>
<td style="text-align: left;">16</td>
<td style="text-align: left;">左(方向)</td>
</tr>
<tr>
<td style="text-align: left;">17</td>
<td style="text-align: left;">右(方向)</td>
</tr>
<tr>
<td style="text-align: left;">18</td>
<td style="text-align: left;">OK(确认)</td>
</tr>
<tr>
<td style="text-align: left;">19</td>
<td style="text-align: left;">菜单</td>
</tr>
<tr>
<td style="text-align: left;">20</td>
<td style="text-align: left;">返回</td>
</tr>
<tr>
<td style="text-align: left;">21</td>
<td style="text-align: left;">主页</td>
</tr>
</tbody>
</table>
<p>设备端-》服务端 :(Response)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;remotectl&quot;,
&quot;sn&quot;:xx,
&quot;result&quot;:x
}</code></pre>
<h2>2.7 服务器点歌指令</h2>
<p>a)服务器发送到点选的歌曲到设备上
b)设备接收到该指令后直接返回成功</p>
<p>方向 服务器-> 设备:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;songselect&quot;,
&quot;sn&quot;: 1,
&quot;songid&quot;: &quot;1123123&quot;,
&quot;istop&quot;: 1
}</code></pre>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌曲点播</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">sn序列号</td>
</tr>
<tr>
<td style="text-align: left;">songid</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌号</td>
</tr>
<tr>
<td style="text-align: left;">istop</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">是否优先点播: 1- 优先点播, 0-正常点播</td>
</tr>
</tbody>
</table>
<p>设备端-》服务端 :(Response)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;songselect&quot;,
&quot;sn&quot;:xx,
&quot;result&quot;:x
}</code></pre>
<h2>2.8 服务器下发已点歌曲优先指令</h2>
<p>a)服务器发送一个将已点中的歌曲提前指令到设备上
b)设备接收到该指令后直接返回成功
c)设备必须 根据ID来处理歌曲
d)命令执行完成后,设备要重新进行歌曲同步</p>
<p>方向 服务器-> 设备:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot; order_insert&quot;,
&quot;sn&quot;: 1,
&quot;ID&quot;: 11,
&quot;songid&quot;: &quot;1020222&quot;
}</code></pre>
<table>
<thead>
<tr>
<th style="text-align: left;">参数</th>
<th style="text-align: left;">类型</th>
<th style="text-align: left;">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">msgtype</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">已点列表歌曲优先</td>
</tr>
<tr>
<td style="text-align: left;">sn</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">sn序号</td>
</tr>
<tr>
<td style="text-align: left;">ID</td>
<td style="text-align: left;">int</td>
<td style="text-align: left;">歌曲已点列表的ID</td>
</tr>
<tr>
<td style="text-align: left;">songid</td>
<td style="text-align: left;">string</td>
<td style="text-align: left;">歌号</td>
</tr>
</tbody>
</table>
<p>设备端-》服务端 :(Response)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot; order_insert&quot;,
&quot;sn&quot;:xx,
&quot;result&quot;:x
}</code></pre>
<h2>2.9 服务器已点歌曲删除指令</h2>
<p>a)服务器发送一个删除已点歌曲的指令到设备上
b)设备接收到该指令后直接返回成功
c)指令执行成功后需要同步歌曲信息到服务器</p>
<p>方向 服务器-> 设备:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot; order_del&quot;,
&quot;sn&quot;: 1,
&quot;songid&quot;: &quot;11111&quot;,
&quot;ID&quot;: 10
}</code></pre>
<p>Response:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;order_del&quot;,
&quot;sn&quot;:1,
&quot;result&quot;:0
}</code></pre>
<h2>2.10.设备心跳(双向收发)</h2>
<p>a)设备必须定期发送心跳保证链路可用,心跳发送周期为10s
b)设备如果检测到心跳没有响应,3次后应该断开重新进行连接
c)服务器30S内如果没有接收到设备的任何心跳 应该认为设备连接已经断开,需要在前端提示设备状态</p>
<p>方向 设备->服务器(Send)</p>
<pre><code class="language-json">{
&quot;msgtype&quot;:&quot;ping&quot;
}</code></pre>
<p>Response:</p>
<pre><code class="language-json">{
&quot;msgtype&quot;: &quot;pong&quot;
}</code></pre>