从python与telnet api进行通信的最佳方式是什么?

时间:2017-02-07 12:25:57

标签: python python-3.x

我有一个来自Denon的多房间扬声器系统叫做Heos,我想用python脚本来控制它。要与多房间系统通信,我必须telnet到设备上的端口1255并发送如下命令:

heos://player/set_play_state?pid=player_id&state=play_state

回复是在json:

{
 "heos": {
 "command": " player/set_play_state ",
 "result": "success",
 "message": "pid='player_id'&state='play_state'"
 }
}

我已成功使用python telnet lib发送如下的简单命令:

command = "heos://player/set_play_state?pid=player_id&state=play_state"
telnet.write(command.encode('ASCII') + b'\r\n')

但是,以可用格式恢复响应的最佳方法是什么?用telnet.read_until循环?我想结果和消息行回到一个干净的变量。

使用telnet与api通信的这种方法感觉有点脏。是否可以使用其他东西,例如socket?

提前致谢

API / CLI在此处记录:http://rn.dmglobal.com/euheos/HEOS_CLI_ProtocolSpecification.pdf

2 个答案:

答案 0 :(得分:1)

虽然可以在这里使用loop_until(),但它将取决于响应JSON的格式,并且依赖它可能是不明智的。

如果远程设备在发送响应后关闭了连接,那么简单的方法就是一个简单的

response = json.loads(telnet.read_all().decode())

如果它对更多命令保持打开状态,那么在您拥有完整的JSON对象之前,您需要继续接收。这是一种可能性,只是一直试图解析JSON,直到成功为止:

response = ''
while True:
    response += telnet.read_some().decode()
    try:
        response = json.loads(response)
        break
    except ValueError:
        pass

无论哪种方式,您的结果和消息都是response['heos']['result']response['heos']['message']

答案 1 :(得分:0)

FWIW,这是我的GitHub repo(受this repo启发)用于控制使用Python的HEOS扬声器。它使用与接受结果类似的方法,但是如果HEOS播放器忙,则另外等待。

def telnet_request(self, command, wait = True):
    """Execute a `command` and return the response(s)."""
    command = self.heosurl + command
    logging.debug("telnet request {}".format(command))
    self.telnet.write(command.encode('ASCII') + b'\r\n')
    response = b''
    while True:
        response += self.telnet.read_some()
        try:
            response = json.loads(response)
            if not wait:
                logging.debug("I accept the first response: {}".format(response))
                break
            # sometimes, I get a response with the message "under
            # process". I might want to wait here
            message = response.get("heos", {}).get("message", "")
            if "command under process" not in message:
                logging.debug("I assume this is the final response: {}".format(response))
                break
            logging.debug("Wait for the final response")
            response = b'' # forget this message
        except ValueError:
            # response is not a complete JSON object
            pass
        except TypeError:
            # response is not a complete JSON object
            pass

    if response.get("result") == "fail":
        logging.warn(response)
        return None

    return response