Ok, maybe it could be helpful to somebody, I have fixed the problem in streaming by using the ezviz platform with some small changes to the ezviz integration source code. Then I implemented a small custom service (“ezviz_service”) in order to use the PTZ function of my camera (C6TC).
Here below more details.
About the streaming matter
In configuration.yaml:
- platform: ezviz
username: <your_ezvizaccount_username>
password: <your_ezvizaccount_password>
cameras:
<camera_serial_number>:
username: <your_camera_username>
password: <your_camera_password>
Then in the ezviz/camera.py source code I simply replaced the initialitation of the self._local_rtsp_port variable with the code here below (in both init and update methods):
self._local_rtsp_port = DEFAULT_RTSP_PORT
if data["local_rtsp_port"] and data["local_rtsp_port"] != 0:
self._local_rtsp_port = data["local_rtsp_port"]
In fact it seems the problem is due to the data[“local_rtsp_port”] which it looks like it is always empty.
About the ptz service matter:
Actually it seems it has never been implemented in the current ezviz integration, so I preferred contacting the [email protected] asking for credentials to access their Ezviz API in order to gather the control of my camera by using basically a couple of REST calls. I guess you can do the same by yourselves if you want to get access to their API, once you get access just add the lines below in your configuration.yaml:
ezviz_service:
app_key: <YOUR_APPKEY_GOT_FROM_EZVIZLIFETEAM>
app_secret: <YOUR_APPSECRET_GOT_FROM_EZVIZLIFETEAM>
serial: <camera_serial_number>
Here below you can get my custom service source code. Hope you appreciate.
import asyncio
import logging
import time
from requests import get, post
CONF_APPKEY = 'app_key'
CONF_APPSECRET = 'app_secret'
CONF_SERIAL = 'serial'
DOMAIN = 'ezviz_service'
DIRECTION_ATTR_VALUE = "direction"
DIRECTION_DEFAULT_NAME = "0"
_LOGGER = logging.getLogger(__name__)
ACCESS_TOKEN = ""
DOMAIN_EZVIZ_API = ""
def setup(hass, config):
"""Set up is called when Home Assistant is loading our component."""
def handle_ptz(call):
_LOGGER.info("hanlde_ptz INIT with AT = %s and DOMAIN = %s", ACCESS_TOKEN, DOMAIN_EZVIZ_API)
if ACCESS_TOKEN == '':
handle_login(call, False)
try:
direction_code = call.data.get(DIRECTION_ATTR_VALUE, DIRECTION_DEFAULT_NAME)
url = DOMAIN_EZVIZ_API + "/api/lapp/device/ptz/start"
_LOGGER.debug("PTZ Up command sending to %s", url)
body = {
"accessToken": ACCESS_TOKEN,
"deviceSerial": DEVICE_SERIAL,
"channelNo": "1",
"direction": direction_code,
"speed": "0",
}
response = post(url, data=body)
#content = response.json()
_LOGGER.debug("PTZ Up command sent")
time.sleep(0.3)
url = DOMAIN_EZVIZ_API + "/api/lapp/device/ptz/stop"
body = {
"accessToken": ACCESS_TOKEN,
"deviceSerial": DEVICE_SERIAL,
"channelNo": "1",
}
response = post(url, data=body)
_LOGGER.debug("PTZ Stop command sent")
except Exception as e:
_LOGGER.error("Something went wrong during PTZ UP request: %s", exc_info=e)
handle_login(call, True)
_LOGGER.debug("hanlde_ptz END")
def handle_login(call, force):
_LOGGER.debug("handle_login INIT with force=%s", force)
global ACCESS_TOKEN
if not(ACCESS_TOKEN != '' or force == False):
url = "https://open.ezvizlife.com/api/lapp/token/get"
body = {
"appKey": APP_KEY,
"appSecret": APP_SECRET,
}
try:
response = post(url, data=body)
content = response.json()
ACCESS_TOKEN = content['data']['accessToken']
global DOMAIN_EZVIZ_API
DOMAIN_EZVIZ_API = content['data']['areaDomain']
_LOGGER.info("Ezviz Login completed with AT = %s and DOMAIN = %s", ACCESS_TOKEN, DOMAIN_EZVIZ_API)
except Exception as e:
_LOGGER.error("Something went wrong during Login request: %s", exc_info=e)
_LOGGER.debug("handle_login END with force=%s", force)
_LOGGER.debug("Registering events...")
hass.services.register(DOMAIN, "login", handle_login)
hass.services.register(DOMAIN, "ptz", handle_ptz)
_LOGGER.debug("Initializing configuration variables...")
APP_KEY = config.get(DOMAIN, {}).get(CONF_APPKEY,'')
APP_SECRET = config.get(DOMAIN, {}).get(CONF_APPSECRET,'')
DEVICE_SERIAL = config.get(DOMAIN, {}).get(CONF_SERIAL,'')
# Return boolean to indicate that initialization was successfully.
return True