Skip to content

Xiaomi Cameras - multiple models#14244

Merged
balloob merged 22 commits into
home-assistant:devfrom
vaidyasr:dev
Jun 15, 2018
Merged

Xiaomi Cameras - multiple models#14244
balloob merged 22 commits into
home-assistant:devfrom
vaidyasr:dev

Conversation

@vaidyasr
Copy link
Copy Markdown
Contributor

@vaidyasr vaidyasr commented May 2, 2018

Description:

Adds support for Xiaomi Cameras running the alternate firmwares.

Related issue (if applicable): N/A

Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#5290

Example entry for configuration.yaml (if applicable):

camera:
  - platform: xiaomi
    name: Hall Camera
    host: '192.168.1.100'
    model: 'xiaofang'
    username: root
    password: my_password_123
    ffmpeg_arguments: '-vf scale=800:450'

Checklist:

  • The code change is tested and works locally.
  • Local tests pass with tox. Your PR cannot be merged unless tests pass

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • New dependencies have been added to the REQUIREMENTS variable (example).
  • New dependencies are only imported inside functions that use them (example).
  • New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • New files were added to .coveragerc.


return 'ftp://{0}:{1}@{2}:{3}{4}/{5}/{6}/{7}'.format(
self.user, self.passwd, self.host, self.port, self.path,
first_dir,latest_dir, videos[-2])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing whitespace after ','

return DEFAULT_BRAND

def get_latest_video_url(self):
"""Retrieve the latest video file from the customized Xiaofang FTP server."""
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (85 > 79 characters)

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 2, 2018

I saw your previous PR (#14238), and I'm wandering: how different is this camera from the Yi ?

The code is almost identical, since they are from the same vendor can we have a single platform that covers both cameras with a configuration option indicating the model ?

@vaidyasr
Copy link
Copy Markdown
Contributor Author

vaidyasr commented May 3, 2018

The folder structure is different than yi model. The folder structure to retrieve in yi model is 2018Y05M01D01H/41M00S.mp4 where as in xiaofang it is 20180501/01/41.mp4. And the latest file writing by the camera is not recognizable by the ffmpeg, so the program has to read last but one file, which is 1 minute lag of live video.

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 3, 2018

I think those differences could fit in the same platform and we would avoid the duplication of much of the 90% of the code...

@vaidyasr
Copy link
Copy Markdown
Contributor Author

vaidyasr commented May 3, 2018

I agree, will try to modify the yi.py code and test it on my end before publishing.

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 3, 2018

Please create a new camera platform "xiaomi" that merges both.

But leave "Yi" alone for now, so we don't break users install right away.

@vaidyasr
Copy link
Copy Markdown
Contributor Author

vaidyasr commented May 3, 2018

I don't get it, this pull is a new platform, how to do it?

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 3, 2018

$ git mv xiaofang.py xiaomi.py and edit the platform to encompass both Yi and Xiaofang cameras

vaidyasr added 2 commits May 3, 2018 17:16
Added Xiaomi Camera to accommodate multiple models like Yi, Xiaofang, etc.
@vaidyasr vaidyasr changed the title Xiaofang 1080p Camera Xiaomi Cameras - multiple models May 3, 2018
Copy link
Copy Markdown
Contributor

@dgomes dgomes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test and please make sure the test covers both models.

_LOGGER.error('Unable to find path: %s', first_dir)
_LOGGER.debug(exc)
return False
if self._model == 'xiaofang':
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define constants at the beginning of the file for all the fixed strings

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean to store 'xiaofang' and 'yi' as constants?

ftp.cwd(first_dir)
except error_perm as exc:
_LOGGER.error('Unable to find path: %s', first_dir)
_LOGGER.debug(exc)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't double log

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both logging are different, 1st one is level 1 and next is level 2.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yet both will log the same issue, just leave one of them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but 1st will report if 20180503 directory exists and 2nd will report if 15 directory exists, there may be cases where the 2nd level will not be there when the camera option was set to only record when there is an motion detection.

Copy link
Copy Markdown
Contributor

@dgomes dgomes May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they will both appear when log level is debug, and since they are in the same except clause they are reporting the same issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do have both models and tested both and worked fine.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a look at existing tests:

https://github.com/home-assistant/home-assistant/tree/dev/tests/components/camera

create a new file for your platform

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I need to create a test?. I don't see it was created for yi already. And it is just a few modification over yi which was already released.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yi camera had no options.

I would mock the FTP server, and validade the existence of the image file in a different path depending on the configured model.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This camera has same options like Yi camera, and am not sure how to do testing, as I am not an expert in python. The code of this one is same as Yi Camera, except one directory above.

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_MODEL): cv.string,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to validate the model

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied.

self._manager = hass.data[DATA_FFMPEG]
self._name = config.get(CONF_NAME)
self.host = config.get(CONF_HOST)
self._model = config.get(CONF_MODEL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required configuration parameters should be retrieved with config[CONF_PARAMETER]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please let me know how to do it?

Copy link
Copy Markdown
Contributor

@dgomes dgomes May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config[CONF_MODEL] and alike for name and host

Copy link
Copy Markdown
Contributor

@dgomes dgomes May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only for required options and options with default value

ftp.cwd(first_dir)
except error_perm as exc:
_LOGGER.error('Unable to find path: %s', first_dir)
_LOGGER.debug(exc)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also implement:

    @property
    def model(self):
        """Return the camera model."""
        return None

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Copy link
Copy Markdown
Contributor Author

@vaidyasr vaidyasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the code per review

ftp.login(self.user, self.passwd)
except error_perm as exc:
_LOGGER.error('There was an error while logging into the camera')
_LOGGER.debug(exc)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still the double logging issue... just merge the two

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though double logging is already there in some of the official released codes, am fixing it

@vaidyasr
Copy link
Copy Markdown
Contributor Author

vaidyasr commented May 4, 2018

I don't understand the failure of continuous-integration. The version of attrs library conflict it seems, can someone confirm.

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 4, 2018

There is currently a PR #14281 related to the issue, wait until it gets merged and then rebase.

@vaidyasr
Copy link
Copy Markdown
Contributor Author

vaidyasr commented May 7, 2018

I have seen the PR has been merged, how do I rebase? please help.

@dgomes
Copy link
Copy Markdown
Contributor

dgomes commented May 7, 2018

There is no need to rebase (CI is already passing)

What is currently missing is a test so coverage doesn't decrease.

Copy link
Copy Markdown
Contributor Author

@vaidyasr vaidyasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes implemented.

_LOGGER = logging.getLogger(__name__)

DEFAULT_BRAND = 'Xiaomi Home Camera'
DEFAULT_PASSWORD = ''
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't used.

async_add_devices,
discovery_info=None):
"""Set up a Xiaomi Camera."""
_LOGGER.debug('Received configuration: %s', config)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't log the config.

try:
ftp.login(self.user, self.passwd)
except error_perm as exc:
_LOGGER.error('There was an error while logging: %s', exc)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write at least: "... while logging in:".

Or rephrase to eg: "Camera login failed:".

return False

if self._model == MODEL_XIAOFANG:
dirs = [d for d in ftp.nlst() if '.' not in d]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same for both models. Can it be moved up?

Changes made per comment


dirs = [d for d in ftp.nlst() if '.' not in d]
if not dirs:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IndentationError: unexpected indent
indentation is not a multiple of four
unexpected indentation

return False


dirs = [d for d in ftp.nlst() if '.' not in d]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many blank lines (2)

_LOGGER.error('Unable to find path: %s - %s', self.path, exc)
return False


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

@dgomes dgomes mentioned this pull request Jun 13, 2018
5 tasks
@ghost ghost assigned balloob Jun 15, 2018
@ghost ghost added in progress and removed almost-done labels Jun 15, 2018
@balloob balloob merged commit c917470 into home-assistant:dev Jun 15, 2018
@ghost ghost removed the in progress label Jun 15, 2018
@disrupted
Copy link
Copy Markdown

@vaidyasr is this supposed to work with the https://github.com/samtap/fang-hacks cfw? do I need to configure anything there since it looks like this component works with mjpeg whereas fang-hacks by default opens a rtsp stream?

@vaidyasr
Copy link
Copy Markdown
Contributor Author

This component works with saved mp4 streams and not the live rtsp stream. For live rtsp stream, you may need to use the ffmpeg camera component.

@home-assistant home-assistant locked and limited conversation to collaborators Jun 19, 2018
@balloob
Copy link
Copy Markdown
Member

balloob commented Jun 25, 2018

I didn't realize that this was for alternative firmware. In that case, the integration should be called after the alternative firmware, not the product.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants