Compare commits

...
276 Commits
Author SHA1 Message Date
Kevin FronczakandGitHub 1ced64de65 Merge pull request #434 from fronzbot/dev
0.17.0
2021-02-15 10:30:52 -05:00
Kevin Fronczak b41460c569 Add 0.17.0 changes 2021-02-15 10:27:32 -05:00
Kevin Fronczak 9ff02de48b Version bump 2021-02-15 10:16:59 -05:00
Kevin FronczakandGitHub 14cbbacc1b Merge pull request #433 from fronzbot/dependabot/pip/pygments-2.8.0
Bump pygments from 2.7.4 to 2.8.0
2021-02-15 10:14:35 -05:00
dependabot-preview[bot]andGitHub 1cadf3488d Bump pygments from 2.7.4 to 2.8.0
Bumps [pygments](https://github.com/pygments/pygments) from 2.7.4 to 2.8.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.7.4...2.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-15 06:09:58 +00:00
Kevin FronczakandGitHub c78f411014 Merge pull request #432 from fronzbot/add-reauth-back
Add reauth param back into login
2021-02-13 11:38:27 -05:00
Kevin Fronczak ab2db14bc8 Add reauth param back into login...may stop emails
- Also added a debug script because I'm tired of typing the same
  commands over and over again when debugging
2021-02-13 11:33:05 -05:00
Kevin FronczakandGitHub 36ff8e4917 Merge pull request #431 from fronzbot/0.17.0rc0
v0.17.0rc0
2021-02-11 23:55:59 -05:00
Kevin Fronczak f42c49d221 RC Version bump 2021-02-11 23:49:11 -05:00
Kevin FronczakandGitHub 114f8fbfa8 Merge pull request #430 from fronzbot/add-clip-record-function
Add camera record function
2021-02-11 23:46:33 -05:00
Kevin FronczakandGitHub 8bbf03fdb4 Merge pull request #429 from fronzbot/add-logout-endpoint
Add logout endpoint
2021-02-11 23:44:49 -05:00
Kevin Fronczak 5b57982b41 Add record function for camera 2021-02-11 23:41:16 -05:00
Kevin Fronczak ecf7a5b13a Add logout endpoint (among some linting improvements) 2021-02-11 23:34:59 -05:00
Kevin FronczakandGitHub f68951fab7 Merge pull request #428 from fronzbot/update-login
Upgrade login, UUID
2021-02-11 22:42:12 -05:00
Kevin Fronczak 23eec5187d Add gen_uid test 2021-02-11 22:32:15 -05:00
Kevin Fronczak caa3e10648 Fixed errant comment 2021-02-11 22:22:05 -05:00
Kevin FronczakandGitHub 4bc0b80eea Merge pull request #427 from fronzbot/dependabot/pip/pre-commit-2.10.1
Bump pre-commit from 2.9.3 to 2.10.1
2021-02-11 22:17:17 -05:00
Kevin Fronczak 959a7dfa85 Modify uid to prefix with BlinkCamera 2021-02-11 11:55:27 -05:00
Kevin Fronczak 9e793b6748 Upgraded login endpoint, fixed uid generation 2021-02-11 11:21:26 -05:00
dependabot-preview[bot]andGitHub c75e057e83 Bump pre-commit from 2.9.3 to 2.10.1
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.9.3 to 2.10.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.9.3...v2.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-08 06:29:34 +00:00
Kevin FronczakandGitHub 6fa4aa6f75 Merge pull request #425 from fronzbot/0.16.5.rc0
0.16.5.rc0
2021-02-05 10:24:00 -05:00
Kevin FronczakandGitHub 89da167404 Update constants.py 2021-02-05 10:22:04 -05:00
Kevin FronczakandGitHub f2520e35fe Merge pull request #424 from fronzbot/fix-vid-download
Add content type to header to fix downloading
2021-02-05 10:21:10 -05:00
Kevin Fronczak aaaaea4dd1 Fix header test 2021-02-05 15:18:09 +00:00
Kevin Fronczak ec67d97809 Add content type to header to fix downloading 2021-02-05 15:11:03 +00:00
Kevin FronczakandGitHub f6118ea4a7 Merge pull request #420 from fronzbot/dependabot/pip/coverage-5.4
Bump coverage from 5.3.1 to 5.4
2021-01-27 07:37:23 -05:00
dependabot-preview[bot]andGitHub d257f676ec Bump coverage from 5.3.1 to 5.4
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3.1 to 5.4.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3.1...coverage-5.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-27 06:09:36 +00:00
Kevin FronczakandGitHub 58f4a9df57 Merge pull request #419 from fronzbot/dependabot/pip/pytest-6.2.2
Bump pytest from 6.2.1 to 6.2.2
2021-01-26 08:10:02 -05:00
dependabot-preview[bot]andGitHub 9d91ce62d3 Bump pytest from 6.2.1 to 6.2.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.1...6.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-26 06:06:01 +00:00
Kevin FronczakandGitHub 511ca99cba Merge pull request #416 from fronzbot/dependabot/pip/pytest-cov-2.11.1
Bump pytest-cov from 2.11.0 to 2.11.1
2021-01-21 09:04:52 -05:00
dependabot-preview[bot]andGitHub 465701810b Bump pytest-cov from 2.11.0 to 2.11.1
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.11.0 to 2.11.1.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.11.0...v2.11.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-21 06:06:32 +00:00
Kevin FronczakandGitHub c8c0ed58df Merge pull request #415 from fronzbot/dependabot/pip/pytest-cov-2.11.0
Bump pytest-cov from 2.10.1 to 2.11.0
2021-01-19 07:30:16 -05:00
dependabot-preview[bot]andGitHub cfe3c10cec Bump pytest-cov from 2.10.1 to 2.11.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.10.1...v2.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-19 06:06:21 +00:00
Kevin FronczakandGitHub 014509bd64 Merge pull request #414 from fronzbot/dependabot/pip/pygments-2.7.4
Bump pygments from 2.7.3 to 2.7.4
2021-01-13 07:53:07 -05:00
dependabot-preview[bot]andGitHub f5d5d34eda Bump pygments from 2.7.3 to 2.7.4
Bumps [pygments](https://github.com/pygments/pygments) from 2.7.3 to 2.7.4.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.7.3...2.7.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-13 06:12:31 +00:00
Kevin FronczakandGitHub 64c8bec614 Merge pull request #405 from fronzbot/dependabot/pip/restructuredtext-lint-1.3.2
Bump restructuredtext-lint from 1.3.1 to 1.3.2
2021-01-05 09:43:00 -05:00
Kevin FronczakandGitHub 1b765035de Merge pull request #408 from fronzbot/dependabot/pip/pre-commit-2.9.3
Bump pre-commit from 2.7.1 to 2.9.3
2021-01-05 09:42:48 -05:00
dependabot-preview[bot]andGitHub 93f46bde6a Bump restructuredtext-lint from 1.3.1 to 1.3.2
Bumps [restructuredtext-lint](https://github.com/twolfson/restructuredtext-lint) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/twolfson/restructuredtext-lint/releases)
- [Changelog](https://github.com/twolfson/restructuredtext-lint/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/twolfson/restructuredtext-lint/compare/1.3.1...1.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-05 14:37:34 +00:00
dependabot-preview[bot]andGitHub 4a09fcf06f Bump pre-commit from 2.7.1 to 2.9.3
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.7.1 to 2.9.3.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.7.1...v2.9.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-05 14:36:38 +00:00
Kevin FronczakandGitHub 12a2ae1326 Merge pull request #407 from fronzbot/dependabot/pip/pygments-2.7.3
Bump pygments from 2.7.1 to 2.7.3
2021-01-05 09:36:22 -05:00
Kevin FronczakandGitHub 325241d56a Merge pull request #411 from fronzbot/dependabot/pip/coverage-5.3.1
Bump coverage from 5.3 to 5.3.1
2021-01-05 09:36:04 -05:00
Kevin FronczakandGitHub 95664fea1f Merge pull request #410 from fronzbot/dependabot/pip/pytest-6.2.1
Bump pytest from 6.1.1 to 6.2.1
2021-01-05 09:35:22 -05:00
dependabot-preview[bot]andGitHub e2b43f4b06 Bump pytest from 6.1.1 to 6.2.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.1.1 to 6.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.1.1...6.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-05 14:29:23 +00:00
Kevin FronczakandGitHub 845c8a2a40 Merge pull request #413 from fronzbot/add-py39
Add py39
2021-01-05 09:27:31 -05:00
Kevin FronczakandGitHub 306f8b6cb4 Update tests.yml 2021-01-05 09:24:04 -05:00
Kevin FronczakandGitHub a704933a35 Update publish.yml 2021-01-05 09:23:29 -05:00
Kevin FronczakandGitHub 8bd09c3726 Delete .gitlab-ci.yml 2021-01-05 09:22:04 -05:00
Kevin FronczakandGitHub 6240364067 Update constants.py 2021-01-05 09:21:36 -05:00
Kevin FronczakandGitHub 9d37cfccd0 Update stale.yml 2021-01-05 09:12:56 -05:00
dependabot-preview[bot]andGitHub 125efd9436 Bump coverage from 5.3 to 5.3.1
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3 to 5.3.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3...coverage-5.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-21 06:32:59 +00:00
dependabot-preview[bot]andGitHub 6701fd39d8 Bump pygments from 2.7.1 to 2.7.3
Bumps [pygments](https://github.com/pygments/pygments) from 2.7.1 to 2.7.3.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.7.1...2.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-07 06:18:02 +00:00
Kevin Fronczak d4edf96f83 Dev version bump 2020-11-23 04:34:49 +00:00
Kevin FronczakandGitHub 37350da1b2 Merge pull request #402 from fronzbot/dev
0.16.4
2020-11-22 23:33:15 -05:00
Kevin FronczakandGitHub a2555a6c40 Update for 0.16.4 2020-11-22 23:31:13 -05:00
Kevin Fronczak c01a6ce16b dev version bump 2020-11-23 04:25:16 +00:00
Kevin Fronczak ab38afa105 dev version bump 2020-11-23 04:06:19 +00:00
Kevin FronczakandGitHub ba3c2e3489 Merge pull request #401 from fronzbot/fix-exception-on-refresh
Added test to catch NoneType error on refresh, fixed offending code
2020-11-22 23:04:31 -05:00
Kevin Fronczak 92a2cc2d9a Added test to catch NoneType error on refresh, fixed offending code 2020-11-23 03:30:15 +00:00
Kevin FronczakandGitHub 0842739197 Merge pull request #395 from fronzbot/fix-stream-format
Fix malformatted stream url for blink mini
2020-10-25 10:09:28 -04:00
Kevin Fronczak f09a66c083 Fix malformatted stream url for blink mini 2020-10-25 14:01:03 +00:00
Kevin FronczakandGitHub 88984365fe Update constants.py 2020-10-06 09:31:45 -04:00
Kevin FronczakandGitHub 469b0c257e Merge pull request #389 from fronzbot/fix-liveview-endpoint
Updated liveview endpoint
2020-10-06 09:29:17 -04:00
Kevin FronczakandGitHub a94f59eb53 Merge pull request #388 from fronzbot/fix-mini-thumb-refresh
Generalized image/video download, fixed non-updating image for minis
2020-10-06 09:23:55 -04:00
Kevin Fronczak eb1fbe90d1 Updated liveview endpoint 2020-10-06 13:20:56 +00:00
Kevin Fronczak b5b7498041 Generalized image/video download, fixed non-updating image for minis 2020-10-06 13:16:05 +00:00
Kevin FronczakandGitHub 828b41197b Merge pull request #387 from fronzbot/move-testtools
Move testtools to requirements_test.txt
2020-10-05 16:33:14 -04:00
Kevin Fronczak b0fed670b9 Move testtools to requirements_test.txt 2020-10-05 20:29:13 +00:00
Kevin FronczakandGitHub f13d177615 Merge pull request #371 from fronzbot/dependabot/pip/pre-commit-2.7.1
Bump pre-commit from 2.6.0 to 2.7.1
2020-10-05 09:53:56 -04:00
Kevin FronczakandGitHub fcce28c9c4 Merge pull request #385 from fronzbot/dependabot/pip/pytest-6.1.1
Bump pytest from 6.0.1 to 6.1.1
2020-10-05 09:53:44 -04:00
Kevin FronczakandGitHub e8e9d4e3cd Update .pre-commit-config.yaml 2020-10-05 09:49:16 -04:00
dependabot-preview[bot]andGitHub 59ef398452 Bump pytest from 6.0.1 to 6.1.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.0.1 to 6.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.0.1...6.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 13:49:12 +00:00
Kevin FronczakandGitHub 80e39845ce Merge pull request #375 from fronzbot/dependabot/pip/pydocstyle-5.1.1
Bump pydocstyle from 5.0.2 to 5.1.1
2020-10-05 09:47:58 -04:00
Kevin FronczakandGitHub cbab673084 Merge pull request #384 from fronzbot/dependabot/pip/flake8-3.8.4
Bump flake8 from 3.8.3 to 3.8.4
2020-10-05 09:47:44 -04:00
Kevin FronczakandGitHub f27df12e64 Merge pull request #379 from fronzbot/dependabot/pip/pygments-2.7.1
Bump pygments from 2.6.1 to 2.7.1
2020-10-05 09:46:08 -04:00
dependabot-preview[bot]andGitHub bdcb3f6203 Bump pydocstyle from 5.0.2 to 5.1.1
Bumps [pydocstyle](https://github.com/PyCQA/pydocstyle) from 5.0.2 to 5.1.1.
- [Release notes](https://github.com/PyCQA/pydocstyle/releases)
- [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/PyCQA/pydocstyle/compare/5.0.2...5.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 13:44:53 +00:00
dependabot-preview[bot]andGitHub f619b20e2a Bump flake8 from 3.8.3 to 3.8.4
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.3 to 3.8.4.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.3...3.8.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 13:44:52 +00:00
Kevin FronczakandGitHub 69aaee3fc4 Merge branch 'dev' into dependabot/pip/pre-commit-2.7.1 2020-10-05 09:44:28 -04:00
Kevin FronczakandGitHub 7140895c58 Merge pull request #370 from fronzbot/dependabot/pip/pylint-2.6.0
Bump pylint from 2.5.3 to 2.6.0
2020-10-05 09:43:33 -04:00
Kevin FronczakandGitHub 190cef875e Attempt to fix coverage 2020-10-05 09:38:15 -04:00
dependabot-preview[bot]andGitHub 7aef8570a5 Bump pylint from 2.5.3 to 2.6.0
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.5.3 to 2.6.0.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/master/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/pylint-2.5.3...pylint-2.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 13:24:47 +00:00
Kevin FronczakandGitHub 721a3ad8f2 Merge pull request #386 from fronzbot/add-codecov-token
Add codecov token to workflow to fix upload issue
2020-10-05 09:21:31 -04:00
Kevin FronczakandGitHub 1b1c30bff0 Add codecov token to workflow to fix upload issue 2020-10-05 09:08:15 -04:00
dependabot-preview[bot]andGitHub 8c23087f89 Bump pre-commit from 2.6.0 to 2.7.1
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.6.0 to 2.7.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.6.0...v2.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 15:10:49 +00:00
Kevin FronczakandGitHub dae2413ed1 Merge pull request #381 from rohitsud/patch-1
Fix readme param and spelling
2020-09-28 11:10:32 -04:00
Kevin FronczakandGitHub cd9792193f Merge pull request #377 from fronzbot/dependabot/pip/coverage-5.3
Bump coverage from 5.2.1 to 5.3
2020-09-28 11:09:35 -04:00
Kevin FronczakandGitHub 75dbd1e498 Merge pull request #368 from fronzbot/dependabot/pip/pytest-cov-2.10.1
Bump pytest-cov from 2.10.0 to 2.10.1
2020-09-27 21:59:53 -04:00
rohitsudandGitHub a374009835 Fix readme param and spelling 2020-09-27 13:06:24 -07:00
dependabot-preview[bot]andGitHub 9a9501635f Bump pygments from 2.6.1 to 2.7.1
Bumps [pygments](https://github.com/pygments/pygments) from 2.6.1 to 2.7.1.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.6.1...2.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-18 06:32:37 +00:00
dependabot-preview[bot]andGitHub e00600c955 Bump coverage from 5.2.1 to 5.3
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2.1 to 5.3.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.2.1...coverage-5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 06:38:09 +00:00
dependabot-preview[bot]andGitHub 141fea542c Bump pytest-cov from 2.10.0 to 2.10.1
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.10.0 to 2.10.1.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.10.0...v2.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-17 08:14:22 +00:00
Kevin Fronczak ed4450778d Dev bump 2020-08-02 03:35:42 +00:00
Kevin FronczakandGitHub 19b7eef123 Merge pull request #363 from fronzbot/dev
0.16.3
2020-08-01 23:33:38 -04:00
Kevin FronczakandGitHub 41d59b1df0 Merge pull request #362 from fronzbot/update-changelog
Update changelog for 0.16.3
2020-08-01 23:29:04 -04:00
Kevin FronczakandGitHub fd104c09da Merge pull request #361 from fronzbot/add-user-agent-everywhere
Add user agent to all headers
2020-08-01 23:28:54 -04:00
Kevin Fronczak 6dbed91426 Update changelog for 0.16.3 2020-08-02 03:24:38 +00:00
Kevin Fronczak cb43f17d75 Add user agent to all headers 2020-08-02 03:22:49 +00:00
Kevin FronczakandGitHub 5ebf278ad3 Merge pull request #360 from fronzbot/dev-bump
Dev version bump
2020-08-01 23:13:46 -04:00
Kevin FronczakandGitHub 6bd8d14190 Merge pull request #359 from fronzbot/dev
0.16.2
2020-08-01 23:12:25 -04:00
Kevin Fronczak 7f782533b8 Dev version bump 2020-08-02 03:09:22 +00:00
Kevin FronczakandGitHub 1790c1beae Merge pull request #358 from fronzbot/bugfix-version-bump
Version bump
2020-08-01 23:07:58 -04:00
Kevin Fronczak 09e1c382d3 Version bump 2020-08-02 03:04:09 +00:00
Kevin FronczakandGitHub ceb2270ee5 Merge pull request #357 from fronzbot/simplify-login
Updated headers to include user-agent, removed extra data at login
2020-08-01 23:01:34 -04:00
Kevin Fronczak 986a3c81f3 Updated headers to include user-agent, removed extra data at login 2020-08-02 02:57:26 +00:00
Kevin FronczakandGitHub 11d6bbb916 Merge pull request #354 from fronzbot/dev-rc-bump
Dev rc bump
2020-07-31 22:15:13 -04:00
Kevin FronczakandGitHub b02f6318a7 Merge pull request #353 from fronzbot/update-app-version
Update app version and set reauth to True...should fix login problems
2020-07-31 22:15:02 -04:00
Kevin FronczakandGitHub c1435e74e8 Merge pull request #352 from fronzbot/dependabot/pip/pytest-6.0.1
Bump pytest from 6.0.0 to 6.0.1
2020-07-31 22:13:28 -04:00
Kevin Fronczak b30da661e5 Dev rc bump 2020-08-01 02:12:42 +00:00
Kevin Fronczak 3a22dddc82 Update app version and set reauth to True...should fix login problems 2020-08-01 02:10:25 +00:00
dependabot-preview[bot]andGitHub a19a17d4dc Bump pytest from 6.0.0 to 6.0.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.0.0...6.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-31 08:16:15 +00:00
Kevin FronczakandGitHub bff6ef92ce Merge pull request #350 from fronzbot/dev-version-bump
Dev bump
2020-07-29 11:38:18 -04:00
Kevin FronczakandGitHub f6ddfbe5cf Merge pull request #349 from fronzbot/dev
0.16.1
2020-07-29 11:32:04 -04:00
Kevin Fronczak 263572eb66 Dev bump 2020-07-29 15:28:13 +00:00
Kevin FronczakandGitHub 3a97a928de Merge pull request #348 from fronzbot/0.16.1-changelog
Updated versions and changelog for 0.16.1
2020-07-29 11:27:26 -04:00
Kevin Fronczak 0322414de1 Updated versions and changelog for 0.16.1 2020-07-29 15:23:59 +00:00
Kevin FronczakandGitHub 1c75e86863 Merge pull request #347 from fronzbot/unpin-reqs
Set min version for reqs instead of pinning
2020-07-29 11:23:11 -04:00
Kevin FronczakandGitHub 0ae71f6367 Merge pull request #345 from fronzbot/dependabot/pip/pytest-6.0.0
Bump pytest from 5.4.3 to 6.0.0
2020-07-29 11:19:38 -04:00
Kevin FronczakandGitHub af7c38695a Merge pull request #344 from fronzbot/dependabot/pip/coverage-5.2.1
Bump coverage from 5.2 to 5.2.1
2020-07-29 11:19:21 -04:00
Kevin Fronczak c741c22876 Set min version for reqs instead of pinning 2020-07-29 15:15:19 +00:00
dependabot-preview[bot]andGitHub 06b9b12eeb Bump pytest from 5.4.3 to 6.0.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.3 to 6.0.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/5.4.3...6.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-29 08:05:56 +00:00
dependabot-preview[bot]andGitHub daf7078f98 Bump coverage from 5.2 to 5.2.1
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2 to 5.2.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.2...coverage-5.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 08:17:40 +00:00
Kevin FronczakandGitHub c2db57ecb3 Merge pull request #341 from fronzbot/dev-bump
Dev version bump
2020-07-20 23:01:51 -04:00
Kevin FronczakandGitHub 1b66eddfb4 Merge pull request #340 from fronzbot/dev
0.16.0
2020-07-20 23:01:30 -04:00
Kevin Fronczak 0336c6a8f8 Dev version bump 2020-07-20 02:24:28 +00:00
Kevin Fronczak 22d3fa9565 Merge remote-tracking branch 'origin/master' into dev 2020-07-20 02:19:27 +00:00
Kevin FronczakandGitHub 9d81973b3a Merge pull request #339 from fronzbot/retry-options
Retry options
2020-07-19 21:47:40 -04:00
Kevin Fronczak fe8eac3dc6 Update documentation 2020-07-20 01:42:07 +00:00
Kevin Fronczak 5fc315201a Add tests for retry options 2020-07-20 01:33:11 +00:00
Kevin Fronczak a9d3d5568b Adding retry options to auth class 2020-07-20 01:25:09 +00:00
Kevin FronczakandGitHub f88dbdaeba Merge pull request #338 from fronzbot/fix-auth-tests
Fix broken test and missing try/except
2020-07-19 21:24:50 -04:00
Kevin Fronczak 48028914de Fix broken test and missing try/except 2020-07-20 01:18:41 +00:00
Kevin FronczakandGitHub fcdb70d246 Merge pull request #337 from fronzbot/remove-exec-info
Removed all exc_info parameters during logging
2020-07-19 20:51:38 -04:00
Kevin Fronczak e8589bfa05 Fix test 2020-07-20 00:48:40 +00:00
Kevin Fronczak 854ffbf26a Removed all exc_info parameters during logging 2020-07-20 00:37:30 +00:00
Kevin FronczakandGitHub ca109f703c Merge pull request #336 from fronzbot/dev-bump
Dev version bump
2020-07-19 20:37:22 -04:00
Kevin Fronczak 82d5a7ea51 Dev version bump 2020-07-20 00:34:06 +00:00
Kevin FronczakandGitHub 79ead7b826 Merge pull request #333 from fronzbot/dependabot/pip/pytest-timeout-1.4.2
Bump pytest-timeout from 1.4.1 to 1.4.2
2020-07-16 13:03:03 -04:00
dependabot-preview[bot]andGitHub 6e360b2bb1 Bump pytest-timeout from 1.4.1 to 1.4.2
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.4.1...1.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-16 08:06:30 +00:00
Kevin FronczakandGitHub 1aaa5b649f Merge pull request #331 from fronzbot/remove-host
Remove host from auth header
2020-07-11 11:24:47 -04:00
Kevin FronczakandGitHub 435f3b9831 Update CHANGES.rst 2020-07-11 10:44:37 -04:00
Kevin FronczakandGitHub bcf0bb5525 Merge pull request #330 from fronzbot/bugfix
Bugfix: remove Host from auth header
2020-07-11 10:42:44 -04:00
Kevin Fronczak 322aae37dc fix test (remove host) 2020-07-11 14:41:44 +00:00
Kevin Fronczak 45cb4028b8 Remove host from auth header 2020-07-11 14:39:45 +00:00
Kevin Fronczak 151d9b7375 Version bump 2020-07-11 14:37:04 +00:00
Kevin Fronczak d393c861d7 bugfix: remove host from auth header 2020-07-11 14:36:37 +00:00
Kevin Fronczak 02c4b2e7e1 Add rst linter to pre-commit and fix flake8 2020-07-11 14:36:06 +00:00
Kevin FronczakandGitHub 77959d6d94 Merge pull request #327 from fronzbot/dependabot/pip/pytest-sugar-0.9.4
Bump pytest-sugar from 0.9.3 to 0.9.4
2020-07-08 22:47:46 -04:00
Kevin FronczakandGitHub ad832c4d2d Merge pull request #326 from fronzbot/dependabot/pip/coverage-5.2
Bump coverage from 5.1 to 5.2
2020-07-08 22:46:54 -04:00
Kevin FronczakandGitHub 0ce2aec139 Merge pull request #328 from fronzbot/remove-unbound-ref
Remove reference to response on exception since it may be unbound
2020-07-08 22:46:29 -04:00
Kevin Fronczak d3761b23ec Remove reference to response on exception since it may be unbound 2020-07-08 17:57:56 +00:00
dependabot-preview[bot]andGitHub cdbd1a4c27 Bump pytest-sugar from 0.9.3 to 0.9.4
Bumps [pytest-sugar](https://github.com/Teemu/pytest-sugar) from 0.9.3 to 0.9.4.
- [Release notes](https://github.com/Teemu/pytest-sugar/releases)
- [Changelog](https://github.com/Teemu/pytest-sugar/blob/master/CHANGES.rst)
- [Commits](https://github.com/Teemu/pytest-sugar/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-07 08:16:07 +00:00
dependabot-preview[bot]andGitHub 2d2e569595 Bump coverage from 5.1 to 5.2
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.1 to 5.2.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.1...coverage-5.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-07 08:15:43 +00:00
Kevin FronczakandGitHub 391373b304 Merge pull request #324 from fronzbot/http-adapter
Modify session to use HTTPAdapter and handle retries
2020-07-02 14:34:45 -04:00
Kevin Fronczak a030f46b4d Modify session to use HTTPAdapter and handle retries 2020-07-02 18:15:29 +00:00
Kevin FronczakandGitHub f6dc22f241 Merge pull request #323 from fronzbot/image-and-video-timeout
Add different timeout for video and image retrieval
2020-07-02 11:40:31 -04:00
Kevin Fronczak 220638e525 Add different timeout for video and image retrieval 2020-07-02 14:50:38 +00:00
Kevin FronczakandGitHub 24b1aac1be Merge pull request #322 from fronzbot/dependabot/pip/pre-commit-2.6.0
Bump pre-commit from 2.5.1 to 2.6.0
2020-07-02 08:46:50 -04:00
dependabot-preview[bot]andGitHub c4608f4258 Bump pre-commit from 2.5.1 to 2.6.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.5.1 to 2.6.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.5.1...v2.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-02 08:15:35 +00:00
Kevin FronczakandGitHub ca19ea62a4 Merge pull request #321 from fronzbot/dependabot/pip/python-slugify-approx-eq-4.0.1
Update python-slugify requirement from ~=4.0.0 to ~=4.0.1
2020-06-30 12:47:24 -04:00
Kevin FronczakandGitHub 2d8f4d8289 Merge pull request #320 from fronzbot/roll-back
Rolled back to rc8, removed v3 auth functionality (poorly thought out)
2020-06-30 12:46:57 -04:00
Kevin Fronczak 24ca9d9617 Fixed request version, improved setup.py requirement import 2020-06-30 16:40:19 +00:00
dependabot-preview[bot]andGitHub 41aa1839b7 Update python-slugify requirement from ~=4.0.0 to ~=4.0.1
Updates the requirements on [python-slugify](https://github.com/un33k/python-slugify) to permit the latest version.
- [Release notes](https://github.com/un33k/python-slugify/releases)
- [Changelog](https://github.com/un33k/python-slugify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/un33k/python-slugify/compare/4.0.0...4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-30 07:53:51 +00:00
Kevin Fronczak 40354e87a0 Rolled back to rc8, removed v3 auth functionality (poorly thought out) 2020-06-29 17:23:15 +00:00
Kevin FronczakandGitHub 0fc74c3f82 Merge pull request #319 from fronzbot/login-fix
Changed the way the new login method switch is handled
2020-06-29 13:06:01 -04:00
Kevin Fronczak 7b150eb1af Changed the way the new login method switch is handled 2020-06-29 17:01:46 +00:00
Kevin FronczakandGitHub f8db8eb3b6 Merge pull request #318 from fronzbot/login-switch
Add option to use v3 login endpoint
2020-06-29 12:49:56 -04:00
Kevin FronczakandGitHub a34b6dec67 Merge pull request #315 from fronzbot/dependabot/pip/requests-approx-eq-2.24.0
Update requests requirement from ~=2.23.0 to ~=2.24.0
2020-06-29 11:54:10 -04:00
Kevin Fronczak bded3eb156 Add option to use v3 login endpoint 2020-06-29 15:46:43 +00:00
dependabot-preview[bot]andGitHub 9ca73934ce Update requests requirement from ~=2.23.0 to ~=2.24.0
Updates the requirements on [requests](https://github.com/psf/requests) to permit the latest version.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/master/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.23.0...v2.24.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-18 08:04:10 +00:00
Kevin FronczakandGitHub e02b429523 Merge pull request #314 from fronzbot/fix-return-error
Fix error with updating owl information during refresh
2020-06-16 14:46:40 -04:00
Kevin Fronczak 22e4b7dabe Fix error with updating owl information during refresh 2020-06-16 18:42:59 +00:00
Kevin FronczakandGitHub 130b5acf84 Merge pull request #312 from fronzbot/dependabot/pip/pytest-timeout-1.4.1
Bump pytest-timeout from 1.4.0 to 1.4.1
2020-06-16 13:54:52 -04:00
Kevin FronczakandGitHub d0fa303c88 Merge pull request #313 from fronzbot/improve-mini-extraction
Broke out homescreen call to prevent back-to-back api calls
2020-06-16 13:54:37 -04:00
Kevin Fronczak dff0746450 Broke out homescreen call to prevent back-to-back api calls 2020-06-16 17:43:22 +00:00
dependabot-preview[bot]andGitHub 815dfd9a8e Bump pytest-timeout from 1.4.0 to 1.4.1
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.4.0...1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 07:58:09 +00:00
Kevin FronczakandGitHub b0ea0566a5 Merge pull request #310 from fronzbot/dependabot/pip/pytest-cov-2.10.0
Bump pytest-cov from 2.9.0 to 2.10.0
2020-06-15 10:57:19 -04:00
dependabot-preview[bot]andGitHub 0167900415 Bump pytest-cov from 2.9.0 to 2.10.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.9.0 to 2.10.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.9.0...v2.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 14:34:40 +00:00
Kevin FronczakandGitHub 9279ba2aa9 Merge pull request #311 from fronzbot/dependabot/pip/pytest-timeout-1.4.0
Bump pytest-timeout from 1.3.4 to 1.4.0
2020-06-15 10:33:14 -04:00
dependabot-preview[bot]andGitHub 2abfc3e843 Bump pytest-timeout from 1.3.4 to 1.4.0
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.3.4 to 1.4.0.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.3.4...1.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 08:34:05 +00:00
Kevin FronczakandGitHub 4ff83585b4 Merge pull request #309 from fronzbot/dev-bump
dev bump
2020-06-14 10:51:47 -04:00
Kevin FronczakandGitHub 3cf2b5e093 dev bump 2020-06-14 10:49:17 -04:00
Kevin FronczakandGitHub 6a7eff6501 Merge pull request #308 from fronzbot/fix-extra-reauth
Removed 'reauth' key from login payload
2020-06-14 10:45:58 -04:00
Kevin Fronczak 3805a41d9f Removed 'reauth' key from login payload 2020-06-14 13:43:58 +00:00
Kevin FronczakandGitHub f8c78fb499 Merge pull request #307 from fronzbot/update-docker-app
Updated docker app to be compatible with 0.16.0 changes
2020-06-13 22:40:35 -04:00
Kevin Fronczak 3314ff85ed Updated docke app to be compatible with 0.16.0 changes 2020-06-14 02:36:57 +00:00
Kevin FronczakandGitHub 67b24eb89a Merge pull request #306 from fronzbot/dev-bump
Dev version bump
2020-06-13 22:18:31 -04:00
Kevin Fronczak d416e42925 Dev version bump 2020-06-14 02:12:43 +00:00
Kevin FronczakandGitHub 17655849ae Merge pull request #305 from fronzbot/disable-owl-option
Add option to skip homescreen check
2020-06-13 22:08:08 -04:00
Kevin Fronczak d9e3761c7b Add option to skip homescreen check 2020-06-14 02:03:22 +00:00
Kevin FronczakandGitHub 382db80584 Merge pull request #304 from fronzbot/codecov-update
Update codecov.yml
2020-06-11 22:57:13 -04:00
Kevin FronczakandGitHub 695dc96340 Update codecov.yml 2020-06-11 22:54:46 -04:00
Kevin FronczakandGitHub 8b1851b647 Merge pull request #303 from fronzbot/support-mini-attached-to-sync
Prevent sync module creation for minis already attached to one
2020-06-11 22:51:24 -04:00
Kevin Fronczak eeaa9cdf6f Prevent sync module creation for minis already attached to one 2020-06-11 23:05:37 +00:00
Kevin FronczakandGitHub 5cd59c049e Merge pull request #302 from fronzbot/dev-bump
Dev version bump
2020-06-10 11:14:03 -04:00
Kevin Fronczak 5d86e0ac9a Dev version bump 2020-06-10 15:10:17 +00:00
Kevin FronczakandGitHub d9136e611f Merge pull request #297 from fronzbot/dependabot/pip/pre-commit-2.5.1
Bump pre-commit from 2.5.0 to 2.5.1
2020-06-10 11:03:38 -04:00
Kevin FronczakandGitHub 5ca1aca3c0 Merge pull request #301 from fronzbot/fix-mini-attributes
Add type check on temperature conversion
2020-06-10 11:03:14 -04:00
Kevin Fronczak 08632ec9ce Add type check on temperature conversion 2020-06-10 14:58:28 +00:00
Kevin FronczakandGitHub 45ba46e637 Merge pull request #300 from fronzbot/blink-mini-arm-support
Add blink mini arm/disarm support
2020-06-10 10:20:42 -04:00
Kevin Fronczak e51740ca89 Removed blink mini arm overload 2020-06-10 14:16:16 +00:00
Kevin Fronczak eb7d7d9601 Add blink mini arm/disarm support
- Updates endpoint for arm/disarm so it's consistent across device types
2020-06-10 14:13:42 +00:00
Kevin FronczakandGitHub c4b70f963c Merge pull request #299 from fronzbot/fix-sync-arm
Fixed missing sync module arm method
2020-06-10 10:13:00 -04:00
Kevin Fronczak b73d122b15 Fixed missing sync module arm method 2020-06-10 14:06:42 +00:00
dependabot-preview[bot]andGitHub db072b9dea Bump pre-commit from 2.5.0 to 2.5.1
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.5.0 to 2.5.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.5.0...v2.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-10 08:27:36 +00:00
Kevin FronczakandGitHub 5c56c903e8 Merge pull request #294 from fronzbot/dev-bump
Dev version bump
2020-06-09 13:54:34 -04:00
Kevin Fronczak 0758fa66d3 Dev version bump 2020-06-09 17:50:31 +00:00
Kevin FronczakandGitHub 6edb89a606 Merge pull request #292 from fronzbot/dependabot/pip/pre-commit-2.5.0
Bump pre-commit from 2.4.0 to 2.5.0
2020-06-09 13:41:13 -04:00
Kevin FronczakandGitHub 7f15827791 Merge pull request #291 from fronzbot/dependabot/pip/flake8-3.8.3
Bump flake8 from 3.8.2 to 3.8.3
2020-06-09 13:40:54 -04:00
Kevin FronczakandGitHub 93d498aafb Merge pull request #290 from fronzbot/add-minis
Add support for Blink Minis
2020-06-09 13:38:40 -04:00
Kevin Fronczak b8da6e2197 Add unsupported notifications, updated Mini thumbnail endpoint 2020-06-09 16:53:33 +00:00
Kevin Fronczak 4f00aac7a2 Fixed missing camera init from owl, cleaned up camera a bit 2020-06-09 15:25:57 +00:00
Kevin Fronczak 7dd32a0dad Make sure cameras are properly merged, initilize minis properly 2020-06-09 13:30:29 +00:00
dependabot-preview[bot]andGitHub eb8f0f6437 Bump pre-commit from 2.4.0 to 2.5.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.4.0...v2.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-09 08:12:59 +00:00
dependabot-preview[bot]andGitHub 8fcd579a69 Bump flake8 from 3.8.2 to 3.8.3
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.2 to 3.8.3.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.2...3.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-09 08:12:37 +00:00
Kevin Fronczak 6479423c6c Fix test 2020-06-09 04:33:11 +00:00
Kevin Fronczak be1a5bf92f Update liveview for mini 2020-06-09 04:10:47 +00:00
Kevin Fronczak 2788ab58ea First cut at blink mini support 2020-06-09 04:04:07 +00:00
Kevin FronczakandGitHub 31de65f155 Merge pull request #289 from fronzbot/add-liveview
Add get_liveview command to camera module
2020-06-08 13:20:03 -04:00
Kevin Fronczak fd2e4ed9a4 Add get_liveview command to camera module 2020-06-08 17:05:54 +00:00
Kevin FronczakandGitHub b029c32744 Merge pull request #288 from fronzbot/use-new-endpoints
Update camera retrieval method (no more homescreen use)
2020-06-08 12:30:59 -04:00
Kevin Fronczak df88be56e9 Change sync get network info method 2020-06-08 16:20:13 +00:00
Kevin Fronczak 816f09b002 Update camera retrieval method (no more homescreen use) 2020-06-08 16:08:19 +00:00
Kevin FronczakandGitHub 507f350ec2 Merge pull request #283 from fronzbot/dependabot/pip/pytest-5.4.3
Bump pytest from 5.4.2 to 5.4.3
2020-06-08 09:48:34 -04:00
Kevin FronczakandGitHub 7067c05c6b Merge pull request #287 from fronzbot/dependabot/pip/pylint-2.5.3
Bump pylint from 2.5.2 to 2.5.3
2020-06-08 09:48:22 -04:00
dependabot-preview[bot]andGitHub 338a10c8a2 Bump pylint from 2.5.2 to 2.5.3
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.5.2 to 2.5.3.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/master/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/pylint-2.5.2...pylint-2.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-08 08:23:41 +00:00
Kevin FronczakandGitHub 44beddac18 Merge branch 'dev' into dependabot/pip/pytest-5.4.3 2020-06-05 22:09:15 -04:00
Kevin FronczakandGitHub 534b5ad6e0 Merge pull request #282 from fronzbot/dependabot/pip/restructuredtext-lint-1.3.1
Bump restructuredtext-lint from 1.3.0 to 1.3.1
2020-06-05 22:09:02 -04:00
Kevin FronczakandGitHub 04ad77ad42 Merge branch 'dev' into dependabot/pip/pytest-5.4.3 2020-06-05 18:38:23 -04:00
Kevin FronczakandGitHub 476042a6e6 Merge branch 'dev' into dependabot/pip/restructuredtext-lint-1.3.1 2020-06-05 18:07:00 -04:00
Kevin FronczakandGitHub d40787499e Merge pull request #285 from fronzbot/add-more-endpoints
Add more api endpoints
2020-06-05 18:06:45 -04:00
Kevin FronczakandGitHub 9e53ebfb05 Merge branch 'dev' into add-more-endpoints 2020-06-05 18:01:56 -04:00
Kevin Fronczak 0455210598 Changed paypal donate to buy me a coffee link 2020-06-05 21:56:11 +00:00
Kevin Fronczak 4d66d8e0c4 Add more api endpoints 2020-06-05 21:54:47 +00:00
dependabot-preview[bot]andGitHub 020b6d9855 Bump pytest from 5.4.2 to 5.4.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/5.4.2...5.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-03 08:22:21 +00:00
dependabot-preview[bot]andGitHub 1d9efabfd6 Bump restructuredtext-lint from 1.3.0 to 1.3.1
Bumps [restructuredtext-lint](https://github.com/twolfson/restructuredtext-lint) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/twolfson/restructuredtext-lint/releases)
- [Changelog](https://github.com/twolfson/restructuredtext-lint/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/twolfson/restructuredtext-lint/compare/1.3.0...1.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-03 08:21:45 +00:00
Kevin FronczakandGitHub b8fc4934e2 Merge pull request #280 from fronzbot/add-user-endpoint
Add new endpoint to get user info
2020-05-30 13:15:16 -04:00
Kevin FronczakandGitHub 37743f78d5 Merge branch 'dev' into add-user-endpoint 2020-05-30 13:12:50 -04:00
Kevin Fronczak 27cddaac70 Add new endpoint to get user info 2020-05-30 16:37:36 +00:00
Kevin FronczakandGitHub 9d828a254c Merge pull request #278 from fronzbot/improve-documentation
Improve documentation
2020-05-28 15:06:11 -04:00
Kevin Fronczak 8bc4544eeb Add rst linter to pre-commit and fix flake8 2020-05-28 18:59:37 +00:00
Kevin Fronczak cec801c39c Add CONTRIBUTING.rst to lint check 2020-05-28 18:57:12 +00:00
Kevin Fronczak 2abf195391 Documentation overhaul 2020-05-28 18:33:36 +00:00
Kevin FronczakandGitHub e6469aea5f Merge pull request #277 from fronzbot/dev-bump
Dev bump to 0.16.0-rc3
2020-05-27 19:43:57 -04:00
Kevin Fronczak 470ab17813 Dev bump to 0.16.0-rc3 2020-05-27 23:33:02 +00:00
Kevin FronczakandGitHub 42e444c0e0 Merge pull request #275 from fronzbot/add-errored-property
Add is_errored property to Auth class
2020-05-27 19:30:14 -04:00
Kevin FronczakandGitHub 2baae9ea45 Merge branch 'dev' into add-errored-property 2020-05-27 19:28:02 -04:00
Kevin FronczakandGitHub 789724a6a3 Merge pull request #276 from fronzbot/dev-bump
Bump dev version
2020-05-27 19:26:51 -04:00
Kevin Fronczak e53439141a Bump dev version 2020-05-27 23:23:50 +00:00
Kevin Fronczak d5ec39113e Add is_errored property to Auth class 2020-05-27 23:19:59 +00:00
Kevin FronczakandGitHub 58117b3daf Merge pull request #274 from fronzbot/remove-auto-refresh
Only refresh token on unauthorized response from request
2020-05-27 19:19:33 -04:00
Kevin FronczakandGitHub 558c190512 Merge branch 'dev' into remove-auto-refresh 2020-05-27 19:17:00 -04:00
Kevin Fronczak 9e124ce5cc Only refresh token on unauthorized response from request 2020-05-27 23:05:51 +00:00
Kevin FronczakandGitHub 396824d38c Merge pull request #273 from fronzbot/add-camera-arm-property
Add arm property to camera, deprecate motion enable method
2020-05-27 17:55:28 -04:00
Kevin FronczakandGitHub cc860c3d03 Merge branch 'dev' into add-camera-arm-property 2020-05-27 17:49:29 -04:00
Kevin FronczakandGitHub 6a5256e9b1 Merge pull request #272 from fronzbot/catch-none-response
Catch all None responses from http requests
2020-05-27 17:48:32 -04:00
Kevin Fronczak 00c2c2cc29 Add arm property to camera, deprecate motion enable method 2020-05-27 21:44:07 +00:00
Kevin Fronczak 4775bda51c Catch all None responses from http requests 2020-05-27 21:27:08 +00:00
Kevin FronczakandGitHub 38fed26742 Merge pull request #269 from fronzbot/increase-timeout
Increase timeout from 2s to 5s
2020-05-26 17:24:20 -04:00
Kevin FronczakandGitHub 99235fbc80 Merge branch 'dev' into increase-timeout 2020-05-26 17:04:33 -04:00
Kevin FronczakandGitHub feef686767 Merge pull request #268 from fronzbot/catch-json-decode-error
Handle json decode error
2020-05-26 17:04:03 -04:00
Kevin Fronczak 1e00f657a7 Increase timeout from 2s to 5s 2020-05-26 21:00:15 +00:00
Kevin Fronczak 672fca6dbf Handle json decode error 2020-05-26 20:44:24 +00:00
Kevin FronczakandGitHub bc85779272 Merge pull request #265 from fronzbot/update-string-format
Update string formatting
2020-05-25 22:05:58 -04:00
Kevin FronczakandGitHub 669fb008d1 Merge branch 'dev' into update-string-format 2020-05-25 22:00:28 -04:00
Kevin FronczakandGitHub 7281241edd Merge pull request #266 from fronzbot/fix-codecov
Update codecov.yml
2020-05-25 22:00:06 -04:00
Kevin Fronczak 9394964688 Update codecov.yml 2020-05-26 01:54:04 +00:00
Kevin Fronczak d8c80c24fc Update string formatting 2020-05-26 01:47:05 +00:00
Kevin FronczakandGitHub 12f7e65d0a Merge pull request #262 from fronzbot/dependabot/pip/pytest-cov-2.9.0
Bump pytest-cov from 2.8.1 to 2.9.0
2020-05-25 21:03:28 -04:00
Kevin FronczakandGitHub d31cb60a17 Merge branch 'dev' into dependabot/pip/pytest-cov-2.9.0 2020-05-25 11:50:04 -04:00
Kevin FronczakandGitHub 1b8bae3d25 Merge pull request #263 from fronzbot/dependabot/pip/flake8-3.8.2
Bump flake8 from 3.8.1 to 3.8.2
2020-05-25 11:49:42 -04:00
Kevin FronczakandGitHub 598b2e4235 Merge branch 'dev' into dependabot/pip/pytest-cov-2.9.0 2020-05-25 09:59:37 -04:00
Kevin FronczakandGitHub 569249a6f4 Merge branch 'dev' into dependabot/pip/flake8-3.8.2 2020-05-25 09:59:27 -04:00
Kevin FronczakandGitHub 754d441111 Merge pull request #264 from fronzbot/dev-bump
Dev version bump
2020-05-25 09:59:12 -04:00
Kevin FronczakandGitHub 4ca9cc21fe Merge branch 'dev' into dependabot/pip/pytest-cov-2.9.0 2020-05-25 09:56:39 -04:00
Kevin Fronczak 2fc3e735c5 Dev version bump 2020-05-25 13:55:42 +00:00
dependabot-preview[bot]andGitHub ca60d99e90 Bump flake8 from 3.8.1 to 3.8.2
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.1 to 3.8.2.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.1...3.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-25 08:36:59 +00:00
dependabot-preview[bot]andGitHub f0445683ca Bump pytest-cov from 2.8.1 to 2.9.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.8.1 to 2.9.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.8.1...v2.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-25 08:36:41 +00:00
41 changed files with 1461 additions and 481 deletions
+3 -2
View File
@@ -1,5 +1,5 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
@@ -8,7 +8,8 @@ daysUntilClose: 7
exemptLabels:
- Priority
- bug
- Help Wanted
- help wanted
- feature request
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true
+2 -1
View File
@@ -33,8 +33,9 @@ jobs:
run: |
tox -r -e cov
- name: Codecov
uses: codecov/codecov-action@v1.0.6
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
file: ./coverage.xml
name: blinkpy
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]
python-version: [3.9]
steps:
- uses: actions/checkout@v2
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.7'
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
+2 -2
View File
@@ -10,11 +10,11 @@ jobs:
build:
runs-on: ${{ matrix.platform }}
strategy:
max-parallel: 3
max-parallel: 4
matrix:
platform:
- ubuntu-latest
python-version: [3.6, 3.7, 3.8]
python-version: [3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2
+1
View File
@@ -14,3 +14,4 @@ build/*
docs/_build
*.log
venv
.session*
-25
View File
@@ -1,25 +0,0 @@
image: python
stages:
- test
before_script:
- curl -O https://bootstrap.pypa.io/get-pip.py
- python get-pip.py
- pip install tox
python35:
image: python:3.5
stage: test
script: tox -e py35
python36:
image: python:3.6
stage: test
script: tox -e py36
lint:
image: python:3.6
stage: test
script: tox -e lint
+8 -3
View File
@@ -8,10 +8,15 @@ repos:
- --quiet
files: ^((blinkpy|tests)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.1
rev: 3.8.3
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.5.0
- pydocstyle==5.0.2
files: ^(homeassistant|tests)/.+\.py$
- pydocstyle==5.1.1
files: ^(blinkpy|tests)/.+\.py$
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
rev: v1.0.0
hooks:
- id: rst-linter
files: /.+\.rst$
+131 -32
View File
@@ -1,10 +1,109 @@
=========
Changelog
-----------
=========
A list of changes between each release
0.17.0 (2021-02-15)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Bugfixes:**
- Fix video downloading bug (`#424 <https://github.com/fronzbot/blinkpy/pull/424>`__)
- Fix repeated authorization email bug (`#432 <https://github.com/fronzbot/blinkpy/pull/432>`__ and `#428 <https://github.com/fronzbot/blinkpy/pull/428>`__)
**New Features:**
- Add logout method (`#429 <https://github.com/fronzbot/blinkpy/pull/429>`__)
- Add camera record method (`#430 <https://github.com/fronzbot/blinkpy/pull/430>`__)
**Other:**
- Add debug script to main repo to help with general debug
- Upgrade login endpoint from v4 to v5
- Add python 3.9 support
- Bump coverage to 5.4
- Bump pytest to 6.2.2
- Bump pytest-cov to 2.11.1
- Bump pygments to 2.8.0
- Bump pre-commit to 2.10.1
- Bump restructuredtext-lint to 1.3.2
0.16.4 (2020-11-22)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Bugfixes:**
- Updated liveview endpoint (`#389 <https://github.com/fronzbot/blinkpy/pull/389>`__)
- Fixed mini thumbnail not updating (`#388 <https://github.com/fronzbot/blinkpy/pull/388>`__)
- Add exception catch to prevent NoneType error on refresh, added test to check behavior as well (`#401 <https://github.com/fronzbot/blinkpy/pull/401>`__)
- Unrelated: had to add two force methods to refresh for testing purposes. Should not change normal usage.
- Fix malformed stream url (`#395 <https://github.com/fronzbot/blinkpy/pull/395>`__)
**All:**
- Moved testtools to requirements_test.txt (`#387 <https://github.com/fronzbot/blinkpy/pull/387>`__)
- Bumped pytest to 6.1.1
- Bumped flake8 to 3.8.4
- Fixed README spelling ((`#381 <https://github.com/fronzbot/blinkpy/pull/381>`__) via @rohitsud)
- Bumped pygments to 2.7.1
- Bumped coverage to 5.3
- Bumped pydocstyle to 5.1.1
- Bumped pre-commit to 2.7.1
- Bumped pylint to 2.6.0
- Bumped pytest-cov to 2.10.1
0.16.3 (2020-08-02)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Add user-agent to all headers
0.16.2 (2020-08-01)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Add user-agent to header at login
- Remove extra data parameters at login (not-needed)
- Bump pytest to 6.0.1
0.16.1 (2020-07-29)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Unpin requirements, set minimum version instead
- Bump coverage to 5.2.1
- Bump pytest to 6.0.0
0.16.0 (2020-07-20)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking Changes:**
- Add arm property to camera, deprecate motion enable method (`#273 <https://github.com/fronzbot/blinkpy/pull/273>`__)
- Complete refactoring of auth logic (breaks all pre-0.16.0 setups!) (`#261 <https://github.com/fronzbot/blinkpy/pull/261>`__)
**New Features:**
- Add is_errored property to Auth class (`#275 <https://github.com/fronzbot/blinkpy/pull/275>`__)
- Add new endpoint to get user infor (`#280 <https://github.com/fronzbot/blinkpy/pull/280>`__)
- Add get_liveview command to camera module (`#289 <https://github.com/fronzbot/blinkpy/pull/289>`__)
- Add blink Mini Camera support (`#290 <https://github.com/fronzbot/blinkpy/pull/290>`__)
- Add option to skip homescreen check (`#305 <https://github.com/fronzbot/blinkpy/pull/305>`__)
- Add different timeout for video and image retrieval (`#323 <https://github.com/fronzbot/blinkpy/pull/323>`__)
- Modifiy session to use HTTPAdapter and handle retries (`#324 <https://github.com/fronzbot/blinkpy/pull/324>`__)
- Add retry option overrides (`#339 <https://github.com/fronzbot/blinkpy/pull/339>`__)
**All changes:**
Please see the change list in the (`Release Notes <https://github.com/fronzbot/releases/tag/v0.16.0>`__)
0.15.1 (2020-07-11)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Bugfix: remove "Host" from auth header (`#330 <https://github.com/fronzbot/blinkpy/pull/330>`__)
0.15.0 (2020-05-08)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking Changes:**
- Removed support for Python 3.5 (3.6 is now the minimum supported version)
@@ -29,7 +128,7 @@ This can be used by instantiating the Blink class with the ``device_id`` paramet
- Fix typos (`#244 <https://github.com/fronzbot/blinkpy/pull/244>`__)
0.14.3 (2020-04-22)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Add time check on recorded videos before determining motion
- Fix motion detection variable suck to ``True``
- Add ability to load credentials from a json file
@@ -37,18 +136,18 @@ This can be used by instantiating the Blink class with the ``device_id`` paramet
- Log response message from server if not attempting a re-authorization
0.14.2 (2019-10-12)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Update dependencies
- Dockerize `(@3ch01c <https://github.com/fronzbot/blinkpy/pull/198>__)`
0.14.1 (2019-06-20)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix timeout problems blocking blinkpy startup
- Updated login urls using ``rest-region`` subdomain
- Removed deprecated thumbanil recovery from homescreen
0.14.0 (2019-05-23)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking Changes:**
- ``BlinkCamera.battery`` no longer reports a percentage, instead it returns a string representing the state of the battery.
@@ -70,11 +169,11 @@ This can be used by instantiating the Blink class with the ``device_id`` paramet
0.13.1 (2019-03-01)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Remove throttle decorator from network status request
0.13.0 (2019-03-01)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking change:**
Wifi status reported in dBm again, instead of bars (which is great). Also, the old ``get_camera_info`` method has changed and requires a ``camera_id`` parameter.
@@ -99,11 +198,11 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
0.12.1 (2019-01-31)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Remove logging improvements since they were incompatible with home-assistant logging
0.12.0 (2019-01-31)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix video api endpoint, re-enables motion detection
- Add improved logging capability
- Add download video method
@@ -111,22 +210,22 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
0.11.2 (2019-01-23)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Hotfix to prevent platform from stalling due to API change
- Motion detection and video recovery broken until new API endpoint discovered
0.11.1 (2019-01-02)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fixed incorrect backup login url
- Added calibrated temperature property for cameras
0.11.0 (2018-11-23)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Added support for multiple sync modules
0.10.3 (2018-11-18)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Use networks endpoint rather than homecreen to retrieve arm/disarm status (`@md-reddevil <https://github.com/fronzbot/blinkpy/pull/119>`__)
- Fix incorrect command status endpoint (`@md-reddevil <https://github.com/fronzbot/blinkpy/pull/118>`__)
- Add extra debug logging
@@ -134,18 +233,18 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
0.10.2 (2018-10-30)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Set minimum required version of the requests library to 2.20.0 due to vulnerability in earlier releases.
- When multiple networks detected, changed log level to ``warning`` from ``error``
0.10.1 (2018-10-18)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix re-authorization bug (fixes `#101 <https://github.com/fronzbot/blinkpy/issues/#101>`__)
- Log an error if saving video that doesn't exist
0.10.0 (2018-10-16)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Moved all API calls to own module for easier maintainability
- Added network ids to sync module and cameras to allow for multi-network use
- Removed dependency on video existance prior to camera setup (fixes `#93 <https://github.com/fronzbot/blinkpy/issues/#93>`__)
@@ -157,7 +256,7 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
- Check if retrieved clip is "None" prior to storing in cache
0.9.0 (2018-09-27)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Complete code refactoring to enable future multi-sync module support
- Add image and video caching to the cameras
- Add internal throttling of system refresh
@@ -168,7 +267,7 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
0.8.1 (2018-09-24)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Update requirements_test.txt
- Update linter versions
- Fix pylint warnings
@@ -184,18 +283,18 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
- Reset the value every system refresh
0.8.0 (2018-05-21)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Added support for battery voltage level (fixes `#64 <https://github.com/fronzbot/blinkpy/issues/64>`__)
- Added motion detection per camera
- Added fully accessible camera configuration dict
- Added celcius property to camera (fixes `#60 <https://github.com/fronzbot/blinkpy/issues/60>`__)
0.7.1 (2018-05-09)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fixed pip 10 import issue during setup (`@fronzbot <https://github.com/fronzbot/blinkpy/pull/61>`__)
0.7.0 (2018-02-08)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fixed style errors for bumped pydocstring and pylint versions
- Changed Blink.cameras dictionary to be case-insensitive (fixes `#35 <https://github.com/fronzbot/blinkpy/issues/35>`__)
- Changed api endpoint for video extraction (fixes `#35 <https://github.com/fronzbot/blinkpy/issues/35>`__ and `#41 <https://github.com/fronzbot/blinkpy/issues/41>`__)
@@ -209,7 +308,7 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
- Added ``attributes`` dictionary to camera object
0.6.0 (2017-05-12)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Removed redundent properties that only called hidden variables
- Revised request wrapper function to be more intelligent
- Added tests to ensure exceptions are caught and handled (100% coverage!)
@@ -217,44 +316,44 @@ Wifi status reported in dBm again, instead of bars (which is great). Also, the
- Added battery level string to reduce confusion with the way Blink reports battery level as integer from 0 to 3
0.5.2 (2017-03-12)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed packaging mishap, same as 0.5.0 otherwise
0.5.0 (2017-03-12)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed region handling problem
- Added rest.piri subdomain as a backup if region can't be found
- Improved the file writing function
- Large test coverage increase
0.4.4 (2017-03-06)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed bug where region id was not being set in the header
0.4.3 (2017-03-05)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Changed to bdist_wheel release
0.4.2 (2017-01-28)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed inability to retrieve motion data due to Key Error
0.4.1 (2017-01-27)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed refresh bug (0.3.1 did not actually fix the problem)
- Image refresh routine added (per camera)
- Dictionary of thumbnails per camera added
- Improved test coverage
0.3.1 (2017-01-25)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Fixed refresh bug (Key Error)
0.3.0 (2017-01-25)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Added device id to camera lookup table
- Added image to file method
0.2.0 (2017-01-21)
^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~
- Initial release of blinkpy
-98
View File
@@ -1,98 +0,0 @@
# Contributing to blinkpy
Everyone is welcome to contribute to blinkpy! The process to get started is described below.
## Fork the Repository
You can do this right in github: just click the 'fork' button at the top right.
## Start Developing
1. Setup Local Repository
```shell
$ git clone https://github.com/<YOUR_GIT_USERNAME>/blinkpy.git
$ cd blinkpy
$ git remote add upstream https://github.com/fronzbot/blinkpy.git
```
2. Create virtualenv and install dependencies
```shell
$ python -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ pip install -r requirements_test.txt
$ pre-commit install
```
3. Create a Local Branch
First, you will want to create a new branch to hold your changes:
``git checkout -b <your-branch-name>``
4. Make changes
Now you can make changes to your code. It is worthwhile to test your code as you progress (see the **Testing** section)
5. Commit Your Changes
To commit changes to your branch, simply add the files you want and the commit them to the branch. After that, you can push to your fork on GitHub:
```shell
$ git add .
$ git commit -m "Put your commit text here. Please be concise, but descriptive."
$ git push origin HEAD
```
6. Submit your pull request on GitHub
- On GitHub, navigate to the [blinkpy](https://github.com/fronzbot/blinkpy) repository.
- In the "Branch" menu, choose the branch that contains your commits (from your fork).
- To the right of the Branch menu, click New pull request.
- The base branch dropdown menu should read `dev`. Use the compare branch drop-down menu to choose the branch you made your changes in.
- Type a title and complete the provided description for your pull request.
- Click Create pull request.
- More detailed instructions can be found here: [Creating a Pull Request](https://help.github.com/articles/creating-a-pull-request/)
7. Prior to merge approval
Finally, the `blinkpy` repository uses continuous integration tools to run tests prior to merging. If there are any problems, you will see a red 'X' next to your pull request. To see what's wrong, you can find your pull request [here](https://travis- ci.org/fronzbot/blinkpy/pull_requests) and click on the failing test to see the logs. Those logs will indicate, as best as they can, what is causing that test to fail.
## Testing
It is important to test the code to make sure your changes don't break anything major and that they pass PEP8 style conventions.
First, you need to locally install ``tox``
```shell
$ pip3 install tox
```
You can then run all of the tests with the following command:
```shell
$ tox
```
### Tips
If you only want to see if you can pass the local tests, you can run `tox -e py35` (or whatever python version you have installed. Only `py35`, `py36`, and `py37` will be accepted). If you just want to check for style violations, you can run `tox -e lint`. Regardless, when you submit a pull request, your code MUST pass both the unit tests, and the linters.
If you need to change anything in `requirements.txt` for any reason, you'll want to regenerate the virtual envrionments used by `tox` by running with the `-r` flag: `tox -r`
If you want to run a single test (perhaps you only changed a small thing in one file) you can run `tox -e py35 -- tests/<testname>.py -x`. This will run the test `<testname>.py` and stop testing upon the first failure, making it easier to figure out why a particular test might be failing. The test structure mimics the library structure, so if you changed something in `sync_module.py`, the associated test file would be in `test_sync_module.py` (ie. the filename is prepended with `test_`.
# Catching Up With Reality
If your code is taking a while to develop, you may be behind the ``dev`` branch, in which case you need to catch up before creating your pull-request. To do this you can run ``git rebase`` as follows (running this on your local branch):
```shell
$ git fetch upstream dev
$ git rebase upstream/dev
```
If rebase detects conflicts, repeat the following process until all changes have been resolved:
1. ``git status`` shows you the filw with a conflict. You will need to edit that file and resolve the lines between ``<<<< | >>>>`.
2. Add the modified file: ``git add <file>`` or ``git add .``.
3. Continue rebase: ``git rebase --continue``.
4. Repeat until all conflicts resolved.
+109
View File
@@ -0,0 +1,109 @@
========================
Contributing to blinkpy
========================
Everyone is welcome to contribute to blinkpy! The process to get started is described below.
Fork the Repository
-------------------
You can do this right in github: just click the 'fork' button at the top right.
Start Developing
-----------------
1. Setup Local Repository
.. code:: bash
$ git clone https://github.com/<YOUR_GIT_USERNAME>/blinkpy.git
$ cd blinkpy
$ git remote add upstream https://github.com/fronzbot/blinkpy.git
2. Create virtualenv and install dependencies
.. code:: bash
$ python -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ pip install -r requirements_test.txt
$ pre-commit install
3. Create a Local Branch
First, you will want to create a new branch to hold your changes:
``git checkout -b <your-branch-name>``
4. Make changes
Now you can make changes to your code. It is worthwhile to test your code as you progress (see the **Testing** section)
5. Commit Your Changes
To commit changes to your branch, simply add the files you want and the commit them to the branch. After that, you can push to your fork on GitHub:
.. code:: bash
$ git add .
$ git commit
$ git push origin HEAD
6. Submit your pull request on GitHub
- On GitHub, navigate to the `blinkpy <https://github.com/fronzbot/blinkpy>`__ repository.
- In the "Branch" menu, choose the branch that contains your commits (from your fork).
- To the right of the Branch menu, click New pull request.
- The base branch dropdown menu should read ``dev``. Use the compare branch drop-down menu to choose the branch you made your changes in.
- Type a title and complete the provided description for your pull request.
- Click Create pull request.
- More detailed instructions can be found here: `Creating a Pull Request` <https://help.github.com/articles/creating-a-pull-request>`__
7. Prior to merge approval
Finally, the ``blinkpy`` repository uses continuous integration tools to run tests prior to merging. If there are any problems, you will see a red 'X' next to your pull request.
Testing
-------
It is important to test the code to make sure your changes don't break anything major and that they pass PEP8 style conventions.
First, you need to locally install ``tox``
.. code:: bash
$ pip install tox
You can then run all of the tests with the following command:
.. code:: bash
$ tox
**Tips**
If you only want to see if you can pass the local tests, you can run ``tox -e py37`` (or whatever python version you have installed. Only ``py36``, ``py37``, and ``py38`` will be accepted). If you just want to check for style violations, you can run ``tox -e lint``. Regardless, when you submit a pull request, your code MUST pass both the unit tests, and the linters.
If you need to change anything in ``requirements.txt`` for any reason, you'll want to regenerate the virtual envrionments used by ``tox`` by running with the ``-r`` flag: ``tox -r``
If you want to run a single test (perhaps you only changed a small thing in one file) you can run ``tox -e py37 -- tests/<testname>.py -x``. This will run the test ``<testname>.py`` and stop testing upon the first failure, making it easier to figure out why a particular test might be failing. The test structure mimics the library structure, so if you changed something in ``sync_module.py``, the associated test file would be in ``test_sync_module.py`` (ie. the filename is prepended with ``test_``.
Catching Up With Reality
-------------------------
If your code is taking a while to develop, you may be behind the ``dev`` branch, in which case you need to catch up before creating your pull-request. To do this you can run ``git rebase`` as follows (running this on your local branch):
.. code:: bash
$ git fetch upstream dev
$ git rebase upstream/dev
If rebase detects conflicts, repeat the following process until all changes have been resolved:
1. ``git status`` shows you the filw with a conflict. You will need to edit that file and resolve the lines between ``<<<< | >>>>``.
2. Add the modified file: ``git add <file>`` or ``git add .``.
3. Continue rebase: ``git rebase --continue``.
4. Repeat until all conflicts resolved.
+48 -16
View File
@@ -4,10 +4,9 @@ A Python library for the Blink Camera system (Python 3.6+)
Like the library? Consider buying me a cup of coffee!
|Donate|
`Buy me a Coffee! <https://buymeacoffee.com/kevinfronczak>`__
Disclaimer:
~~~~~~~~~~~~~~~
**Disclaimer:**
Published under the MIT license - See LICENSE file for more details.
"Blink Wire-Free HS Home Monitoring & Alert Systems" is a trademark owned by Immedia Inc., see www.blinkforhome.com for more information.
@@ -18,11 +17,11 @@ Original protocol hacking by MattTW : https://github.com/MattTW/BlinkMonitorProt
API calls faster than 60 seconds is not recommended as it can overwhelm Blink's servers. Please use this module responsibly.
Installation
================
``pip3 install blinkpy``
-------------
``pip install blinkpy``
Installing Development Version
==================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To install the current development version, perform the following steps. Note that the following will create a blinkpy directory in your home area:
.. code:: bash
@@ -35,12 +34,12 @@ To install the current development version, perform the following steps. Note t
$ pip3 install --upgrade dist/*.whl
If you'd like to contribute to this library, please read the `contributing instructions <https://github.com/fronzbot/blinkpy/blob/dev/CONTRIBUTING.md>`__.
If you'd like to contribute to this library, please read the `contributing instructions <https://github.com/fronzbot/blinkpy/blob/dev/CONTRIBUTING.rst>`__.
For more information on how to use this library, please `read the docs <https://blinkpy.readthedocs.io/en/latest/>`__.
Purpose
===========
-------
This library was built with the intention of allowing easy communication with Blink camera systems, specifically to support the `Blink component <https://home-assistant.io/components/blink>`__ in `homeassistant <https://home-assistant.io/>`__.
Quick Start
@@ -58,7 +57,7 @@ The simplest way to use this package from a terminal is to call ``Blink.start()`
This flow will prompt you for your username and password. Once entered, if you likely will need to send a 2FA key to the blink servers (this pin is sent to your email address). When you receive this pin, enter at the prompt and the Blink library will proceed with setup.
Starting blink without a prompt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------
In some cases, having an interactive command-line session is not desired. In this case, you will need to set the ``Blink.auth.no_prompt`` value to ``True``. In addition, since you will not be prompted with a username and password, you must supply the login data to the blink authentication handler. This is best done by instantiating your own auth handler with a dictionary containing at least your username and password.
.. code:: python
@@ -82,7 +81,7 @@ Since you will not be prompted for any 2FA pin, you must call the ``blink.auth.s
Supplying credentials from file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------
Other use cases may involved loading credentials from a file. This file must be ``json`` formatted and contain a minimum of ``username`` and ``password``. A built in function in the ``blinkpy.helpers.util`` module can aid in loading this file. Note, if ``no_prompt`` is desired, a similar flow can be followed as above.
.. code:: python
@@ -98,7 +97,7 @@ Other use cases may involved loading credentials from a file. This file must be
Saving credentials
~~~~~~~~~~~~~~~~~~~
-------------------
This library also allows you to save your credentials to use in future sessions. Saved information includes authentication tokens as well as unique ids which should allow for a more streamlined experience and limits the frequency of login requests. This data can be saved as follows (it can then be loaded by following the instructions above for supplying credentials from a file):
.. code:: python
@@ -107,7 +106,7 @@ This library also allows you to save your credentials to use in future sessions.
Getting cameras
~~~~~~~~~~~~~~~~
----------------
Cameras are instantiated as individual ``BlinkCamera`` classes within a ``BlinkSyncModule`` instance. All of your sync modules are stored within the ``Blink.sync`` dictionary and can be accessed using the name of the sync module as the key (this is the name of your sync module in the Blink App).
The below code will display cameras and their available attributes:
@@ -138,9 +137,44 @@ The ``blinkpy`` api also allows for saving images and videos to a file and snapp
camera.image_to_file('/local/path/for/image.jpg')
camera.video_to_file('/local/path/for/video.mp4')
Arming Blink
-------------
Methods exist to arm/disarm the sync module, as well as enable/disable motion detection for individual cameras. This is done as follows:
.. code:: python
# Arm a sync module
blink.sync["SYNC MODULE NAME"].arm = True
# Disarm a sync module
blink.sync["SYNC MODULE NAME"].disarm = False
# Print arm status of a sync module - a system refresh should be performed first
blink.refresh()
sync = blink.sync["SYNC MODULE NAME"]
print(f"{sync.name} status: {sync.arm}")
Similar methods exist for individual cameras:
.. code:: python
camera = blink.cameras["SOME CAMERA NAME"]
# Enable motion detection on a camera
camera.arm = True
# Disable motion detection on a camera
camera.arm = False
# Print arm status of a sync module - a system refresh should be performed first
blink.refresh()
print(f"{camera.name} status: {camera.arm}")
Download videos
~~~~~~~~~~~~~~~~
You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``page=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specidy one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras.
----------------
You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``stop=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specify one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras.
Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34am to the ``/home/blink`` directory:
@@ -157,7 +191,5 @@ Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34a
:target: https://pypi.python.org/pypi/blinkpy
.. |Docs| image:: https://readthedocs.org/projects/blinkpy/badge/?version=latest
:target: http://blinkpy.readthedocs.io/en/latest/?badge=latest
.. |Donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UR6Z2B8GXYUCC
.. |Codestyle| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
+14 -6
View File
@@ -1,11 +1,12 @@
"""Script to run blinkpy as an app."""
from os import environ
from datetime import datetime, timedelta
from blinkpy import blinkpy
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load
USERNAME = environ.get("USERNAME")
PASSWORD = environ.get("PASSWORD")
CREDFILE = environ.get("CREDFILE")
TIMEDELTA = timedelta(environ.get("TIMEDELTA", 1))
@@ -21,11 +22,18 @@ def download_videos(blink, save_dir="/media"):
def start():
"""Startup blink app."""
blink = blinkpy.Blink(username=USERNAME, password=PASSWORD)
blink = Blink()
blink.auth = Auth(json_load(CREDFILE))
blink.start()
return blink
def main():
"""Run the app."""
blink = start()
download_videos(blink)
blink.save(CREDFILE)
if __name__ == "__main__":
BLINK = start()
download_videos(BLINK)
main()
+74 -44
View File
@@ -3,11 +3,11 @@
import logging
from json import dumps
from blinkpy.helpers.util import get_time, Throttle
from blinkpy.helpers.constants import DEFAULT_URL
from blinkpy.helpers.constants import DEFAULT_URL, TIMEOUT, DEFAULT_USER_AGENT
_LOGGER = logging.getLogger(__name__)
MIN_THROTTLE_TIME = 2
MIN_THROTTLE_TIME = 5
def request_login(
@@ -20,21 +20,22 @@ def request_login(
:param url: Login url.
:login_data: Dictionary containing blink login data.
"""
headers = {"Host": DEFAULT_URL, "Content-Type": "application/json"}
headers = {
"Host": DEFAULT_URL,
"Content-Type": "application/json",
"user-agent": DEFAULT_USER_AGENT,
}
data = dumps(
{
"email": login_data["username"],
"password": login_data["password"],
"notification_key": login_data["notification_key"],
"unique_id": login_data["uid"],
"app_version": "6.0.7 (520300) #afb0be72a",
"device_identifier": login_data["device_id"],
"client_name": "Computer",
"client_type": "android",
"os_version": "5.1.1",
"reauth": "true",
"reauth": True,
}
)
return auth.query(
url=url,
headers=headers,
@@ -47,18 +48,39 @@ def request_login(
def request_verify(auth, blink, verify_key):
"""Send verification key to blink servers."""
url = "{}/api/v4/account/{}/client/{}/pin/verify".format(
blink.urls.base_url, blink.account_id, blink.client_id
)
url = f"{blink.urls.base_url}/api/v4/account/{blink.account_id}/client/{blink.client_id}/pin/verify"
data = dumps({"pin": verify_key})
return auth.query(
url=url, headers=auth.header, data=data, json_resp=False, reqtype="post",
)
def request_logout(blink):
"""Logout of blink servers."""
url = f"{blink.urls.base_url}/api/v4/account/{blink.account_id}/client/{blink.client_id}/logout"
return http_post(blink, url=url)
def request_networks(blink):
"""Request all networks information."""
url = "{}/networks".format(blink.urls.base_url)
url = f"{blink.urls.base_url}/networks"
return http_get(blink, url)
def request_network_update(blink, network):
"""
Request network update.
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = f"{blink.urls.base_url}/network/{network}/update"
return http_post(blink, url)
def request_user(blink):
"""Get user information from blink servers."""
url = f"{blink.urls.base_url}/user"
return http_get(blink, url)
@@ -69,7 +91,7 @@ def request_network_status(blink, network):
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/network/{}".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/network/{network}"
return http_get(blink, url)
@@ -80,7 +102,7 @@ def request_syncmodule(blink, network):
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/network/{}/syncmodules".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/network/{network}/syncmodules"
return http_get(blink, url)
@@ -92,7 +114,7 @@ def request_system_arm(blink, network):
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/network/{}/arm".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/state/arm"
return http_post(blink, url)
@@ -104,7 +126,7 @@ def request_system_disarm(blink, network):
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/network/{}/disarm".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/state/disarm"
return http_post(blink, url)
@@ -116,16 +138,14 @@ def request_command_status(blink, network, command_id):
:param network: Sync module network id.
:param command_id: Command id to check.
"""
url = "{}/network/{}/command/{}".format(blink.urls.base_url, network, command_id)
url = f"{blink.urls.base_url}/network/{network}/command/{command_id}"
return http_get(blink, url)
@Throttle(seconds=MIN_THROTTLE_TIME)
def request_homescreen(blink):
"""Request homescreen info."""
url = "{}/api/v3/accounts/{}/homescreen".format(
blink.urls.base_url, blink.account_id
)
url = f"{blink.urls.base_url}/api/v3/accounts/{blink.account_id}/homescreen"
return http_get(blink, url)
@@ -137,7 +157,7 @@ def request_sync_events(blink, network):
:param blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/events/network/{}".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/events/network/{network}"
return http_get(blink, url)
@@ -150,9 +170,7 @@ def request_new_image(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request new image from.
"""
url = "{}/network/{}/camera/{}/thumbnail".format(
blink.urls.base_url, network, camera_id
)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/thumbnail"
return http_post(blink, url)
@@ -165,14 +183,14 @@ def request_new_video(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request new video from.
"""
url = "{}/network/{}/camera/{}/clip".format(blink.urls.base_url, network, camera_id)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/clip"
return http_post(blink, url)
@Throttle(seconds=MIN_THROTTLE_TIME)
def request_video_count(blink):
"""Request total video count."""
url = "{}/api/v2/videos/count".format(blink.urls.base_url)
url = f"{blink.urls.base_url}/api/v2/videos/count"
return http_get(blink, url)
@@ -185,9 +203,7 @@ def request_videos(blink, time=None, page=0):
:param page: Page number to get videos from.
"""
timestamp = get_time(time)
url = "{}/api/v1/accounts/{}/media/changed?since={}&page={}".format(
blink.urls.base_url, blink.account_id, timestamp, page
)
url = f"{blink.urls.base_url}/api/v1/accounts/{blink.account_id}/media/changed?since={timestamp}&page={page}"
return http_get(blink, url)
@@ -198,7 +214,7 @@ def request_cameras(blink, network):
:param Blink: Blink instance.
:param network: Sync module network id.
"""
url = "{}/network/{}/cameras".format(blink.urls.base_url, network)
url = f"{blink.urls.base_url}/network/{network}/cameras"
return http_get(blink, url)
@@ -210,12 +226,32 @@ def request_camera_info(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request info from.
"""
url = "{}/network/{}/camera/{}/config".format(
blink.urls.base_url, network, camera_id
)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/config"
return http_get(blink, url)
def request_camera_usage(blink):
"""
Request camera status.
:param blink: Blink instance.
"""
url = f"{blink.urls.base_url}/api/v1/camera/usage"
return http_get(blink, url)
def request_camera_liveview(blink, network, camera_id):
"""
Request camera liveview.
:param blink: Blink instance.
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request liveview from.
"""
url = f"{blink.urls.base_url}/api/v5/accounts/{blink.account_id}/networks/{network}/cameras/{camera_id}/liveview"
return http_post(blink, url)
def request_camera_sensors(blink, network, camera_id):
"""
Request camera sensor info for one camera.
@@ -224,9 +260,7 @@ def request_camera_sensors(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request sesnor info from.
"""
url = "{}/network/{}/camera/{}/signals".format(
blink.urls.base_url, network, camera_id
)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/signals"
return http_get(blink, url)
@@ -239,9 +273,7 @@ def request_motion_detection_enable(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to enable.
"""
url = "{}/network/{}/camera/{}/enable".format(
blink.urls.base_url, network, camera_id
)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/enable"
return http_post(blink, url)
@@ -253,13 +285,11 @@ def request_motion_detection_disable(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to disable.
"""
url = "{}/network/{}/camera/{}/disable".format(
blink.urls.base_url, network, camera_id
)
url = f"{blink.urls.base_url}/network/{network}/camera/{camera_id}/disable"
return http_post(blink, url)
def http_get(blink, url, stream=False, json=True, is_retry=False):
def http_get(blink, url, stream=False, json=True, is_retry=False, timeout=TIMEOUT):
"""
Perform an http get request.
@@ -279,7 +309,7 @@ def http_get(blink, url, stream=False, json=True, is_retry=False):
)
def http_post(blink, url, is_retry=False):
def http_post(blink, url, is_retry=False, timeout=TIMEOUT):
"""
Perform an http post request.
+101 -26
View File
@@ -2,10 +2,16 @@
import logging
from functools import partial
from requests import Request, Session, exceptions
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from blinkpy import api
from blinkpy.helpers import util
from blinkpy.helpers.constants import BLINK_URL, LOGIN_ENDPOINT
from blinkpy.helpers import errors as ERROR
from blinkpy.helpers.constants import (
BLINK_URL,
DEFAULT_USER_AGENT,
LOGIN_ENDPOINT,
TIMEOUT,
)
_LOGGER = logging.getLogger(__name__)
@@ -33,6 +39,7 @@ class Auth:
self.client_id = login_data.get("client_id", None)
self.account_id = login_data.get("account_id", None)
self.login_response = None
self.is_errored = False
self.no_prompt = no_prompt
self.session = self.create_session()
@@ -51,12 +58,31 @@ class Auth:
"""Return authorization header."""
if self.token is None:
return None
return {"Host": self.host, "TOKEN_AUTH": self.token}
return {
"TOKEN_AUTH": self.token,
"user-agent": DEFAULT_USER_AGENT,
"content-type": "application/json",
}
def create_session(self):
def create_session(self, opts=None):
"""Create a session for blink communication."""
if opts is None:
opts = {}
backoff = opts.get("backoff", 1)
retries = opts.get("retries", 3)
retry_list = opts.get("retry_list", [429, 500, 502, 503, 504])
sess = Session()
sess.get = partial(sess.get, timeout=10)
assert_status_hook = [
lambda response, *args, **kwargs: response.raise_for_status()
]
sess.hooks["response"] = assert_status_hook
retry = Retry(
total=retries, backoff_factor=backoff, status_forcelist=retry_list
)
adapter = HTTPAdapter(max_retries=retry)
sess.mount("https://", adapter)
sess.mount("http://", adapter)
sess.get = partial(sess.get, timeout=TIMEOUT)
return sess
def prepare_request(self, url, headers, data, reqtype):
@@ -82,24 +108,37 @@ class Auth:
if response.status_code == 200:
return response.json()
raise LoginError
except AttributeError:
raise LoginError
except AttributeError as error:
raise LoginError from error
def logout(self, blink):
"""Log out."""
return api.request_logout(blink)
def refresh_token(self):
"""Refresh auth token."""
self.is_errored = True
try:
_LOGGER.info("Token expired, attempting automatic refresh.")
self.login_response = self.login()
self.region_id = self.login_response["region"]["tier"]
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["authtoken"]["authtoken"]
self.client_id = self.login_response["client"]["id"]
self.account_id = self.login_response["account"]["id"]
except KeyError:
self.extract_login_info()
self.is_errored = False
except LoginError as error:
_LOGGER.error("Login endpoint failed. Try again later.")
raise TokenRefreshFailed from error
except (TypeError, KeyError) as error:
_LOGGER.error("Malformed login response: %s", self.login_response)
raise TokenRefreshFailed
raise TokenRefreshFailed from error
return True
def extract_login_info(self):
"""Extract login info from login response."""
self.region_id = self.login_response["account"]["tier"]
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["auth"]["token"]
self.client_id = self.login_response["account"]["client_id"]
self.account_id = self.login_response["account"]["account_id"]
def startup(self):
"""Initialize tokens for communication."""
self.validate_login()
@@ -109,15 +148,21 @@ class Auth:
def validate_response(self, response, json_resp):
"""Check for valid response."""
if not json_resp:
self.is_errored = False
return response
json_data = response.json()
self.is_errored = True
try:
if json_data["code"] in ERROR.BLINK_ERRORS:
if response.status_code in [101, 401]:
raise UnauthorizedError
if response.status_code == 404:
raise exceptions.ConnectionError
json_data = response.json()
except KeyError:
pass
except (AttributeError, ValueError) as error:
raise BlinkBadResponse from error
self.is_errored = False
return json_data
def query(
@@ -129,6 +174,7 @@ class Auth:
stream=False,
json_resp=True,
is_retry=False,
timeout=TIMEOUT,
):
"""
Perform server requests.
@@ -139,29 +185,47 @@ class Auth:
:param reqtype: Can be 'get' or 'post' (default: 'get')
:param stream: Stream response? True/FALSE
:param json_resp: Return JSON response? TRUE/False
:param is_retry: Is this a retry attempt? True/FALSE
:param is_retry: Is this part of a re-auth attempt? True/FALSE
"""
req = self.prepare_request(url, headers, data, reqtype)
try:
response = self.session.send(req, stream=stream)
response = self.session.send(req, stream=stream, timeout=timeout)
return self.validate_response(response, json_resp)
except (exceptions.ConnectionError, exceptions.Timeout, TokenRefreshFailed):
except (exceptions.ConnectionError, exceptions.Timeout):
_LOGGER.error(
"Connection error. Endpoint %s possibly down or throttled.", url,
)
except BlinkBadResponse:
code = None
reason = None
try:
code = response.status_code
reason = response.reason
except AttributeError:
pass
_LOGGER.error(
"Expected json response from %s, but received: %s: %s",
url,
code,
reason,
)
except UnauthorizedError:
try:
if not is_retry:
self.refresh_token()
return self.query(
url=url,
data=data,
headers=headers,
headers=self.header,
reqtype=reqtype,
stream=stream,
json_resp=json_resp,
is_retry=True,
timeout=timeout,
)
except (TokenRefreshFailed, LoginError):
_LOGGER.error("Endpoint %s failed. Unable to refresh login tokens", url)
_LOGGER.error("Endpoint %s failed", url)
_LOGGER.error("Unable to access %s after token refresh.", url)
except TokenRefreshFailed:
_LOGGER.error("Unable to refresh token.")
return None
def send_auth_key(self, blink, key):
@@ -171,6 +235,9 @@ class Auth:
try:
json_resp = response.json()
blink.available = json_resp["valid"]
if not json_resp["valid"]:
_LOGGER.error("%s", json_resp["message"])
return False
except (KeyError, TypeError):
_LOGGER.error("Did not receive valid response from server.")
return False
@@ -179,7 +246,7 @@ class Auth:
def check_key_required(self):
"""Check if 2FA key is required."""
try:
if self.login_response["client"]["verification_required"]:
if self.login_response["account"]["client_verification_required"]:
return True
except (KeyError, TypeError):
pass
@@ -192,3 +259,11 @@ class TokenRefreshFailed(Exception):
class LoginError(Exception):
"""Class to throw failed login exception."""
class BlinkBadResponse(Exception):
"""Class to throw bad json response exception."""
class UnauthorizedError(Exception):
"""Class to throw an unauthorized access error."""
+80 -27
View File
@@ -23,17 +23,17 @@ from dateutil.parser import parse
from slugify import slugify
from blinkpy import api
from blinkpy.sync_module import BlinkSyncModule
from blinkpy.sync_module import BlinkSyncModule, BlinkOwl
from blinkpy.helpers import util
from blinkpy.helpers.constants import (
DEFAULT_MOTION_INTERVAL,
DEFAULT_REFRESH,
MIN_THROTTLE_TIME,
TIMEOUT_MEDIA,
)
from blinkpy.helpers.constants import __version__
from blinkpy.auth import Auth, TokenRefreshFailed, LoginError
_LOGGER = logging.getLogger(__name__)
@@ -41,7 +41,10 @@ class Blink:
"""Class to initialize communication."""
def __init__(
self, refresh_rate=DEFAULT_REFRESH, motion_interval=DEFAULT_MOTION_INTERVAL,
self,
refresh_rate=DEFAULT_REFRESH,
motion_interval=DEFAULT_MOTION_INTERVAL,
no_owls=False,
):
"""
Initialize Blink system.
@@ -52,6 +55,7 @@ class Blink:
Defaults to last refresh time.
Useful for preventing motion_detected property
from de-asserting too quickly.
:param no_owls: Disable searching for owl entries (blink mini cameras only known entity). Prevents an uneccessary API call if you don't have these in your network.
"""
self.auth = Auth()
self.account_id = None
@@ -68,23 +72,26 @@ class Blink:
self.version = __version__
self.available = False
self.key_required = False
self.homescreen = {}
self.no_owls = no_owls
@util.Throttle(seconds=MIN_THROTTLE_TIME)
def refresh(self, force=False):
def refresh(self, force=False, force_cache=False):
"""
Perform a system refresh.
:param force: Force an update of the camera data
:param force: Used to override throttle, resets refresh
:param force_cache: Used to force update without overriding throttle
"""
if self.check_if_ok_to_update() or force:
if self.check_if_ok_to_update() or force or force_cache:
if not self.available:
self.auth.refresh_token()
self.setup_post_verify()
self.get_homescreen()
for sync_name, sync_module in self.sync.items():
_LOGGER.debug("Attempting refresh of sync %s", sync_name)
sync_module.refresh(force_cache=force)
if not force:
sync_module.refresh(force_cache=(force or force_cache))
if not force_cache:
# Prevents rapid clearing of motion detect property
self.last_refresh = int(time.time())
return True
@@ -96,6 +103,7 @@ class Blink:
self.auth.startup()
self.setup_login_ids()
self.setup_urls()
self.get_homescreen()
except (LoginError, TokenRefreshFailed, BlinkSetupError):
_LOGGER.error("Cannot setup Blink platform.")
self.available = False
@@ -128,7 +136,8 @@ class Blink:
for name, network_id in networks.items():
sync_cameras = cameras.get(network_id, {})
self.setup_sync_module(name, network_id, sync_cameras)
self.cameras = self.merge_cameras()
self.cameras = self.merge_cameras()
self.available = True
self.key_required = False
@@ -139,20 +148,57 @@ class Blink:
self.sync[name] = BlinkSyncModule(self, name, network_id, cameras)
self.sync[name].start()
def get_homescreen(self):
"""Get homecreen information."""
if self.no_owls:
_LOGGER.debug("Skipping owl extraction.")
self.homescreen = {}
return
self.homescreen = api.request_homescreen(self)
def setup_owls(self):
"""Check for mini cameras."""
network_list = []
camera_list = []
try:
for owl in self.homescreen["owls"]:
name = owl["name"]
network_id = str(owl["network_id"])
if network_id in self.network_ids:
camera_list.append(
{network_id: {"name": name, "id": network_id, "type": "mini"}}
)
continue
if owl["onboarded"]:
network_list.append(str(network_id))
self.sync[name] = BlinkOwl(self, name, network_id, owl)
self.sync[name].start()
except KeyError:
# No sync-less devices found
pass
self.network_ids.extend(network_list)
return camera_list
def setup_camera_list(self):
"""Create camera list for onboarded networks."""
all_cameras = {}
response = api.request_homescreen(self)
response = api.request_camera_usage(self)
try:
for camera in response["cameras"]:
camera_network = str(camera["network_id"])
for network in response["networks"]:
camera_network = str(network["network_id"])
if camera_network not in all_cameras:
all_cameras[camera_network] = []
all_cameras[camera_network].append(
{"name": camera["name"], "id": camera["id"]}
)
for camera in network["cameras"]:
all_cameras[camera_network].append(
{"name": camera["name"], "id": camera["id"]}
)
mini_cameras = self.setup_owls()
for camera in mini_cameras:
for network, camera_info in camera.items():
all_cameras[network].append(camera_info)
return all_cameras
except KeyError:
except (KeyError, TypeError):
_LOGGER.error("Unable to retrieve cameras from response %s", response)
raise BlinkSetupError
@@ -176,7 +222,7 @@ class Blink:
response = api.request_networks(self)
try:
self.networks = response["summary"]
except KeyError:
except (KeyError, TypeError):
raise BlinkSetupError
def setup_network_ids(self):
@@ -225,7 +271,7 @@ class Blink:
:param path: Path to write files. /path/<cameraname>_<recorddate>.mp4
:param since: Date and time to get videos from.
Ex: "2018/07/28 12:33:00" to retrieve videos since
July 28th 2018 at 12:33:00
July 28th 2018 at 12:33:00
:param camera: Camera name to retrieve. Defaults to "all".
Use a list for multiple cameras.
:param stop: Page to stop on (~25 items per page. Default page 10).
@@ -250,8 +296,8 @@ class Blink:
try:
result = response["media"]
if not result:
raise IndexError
except (KeyError, IndexError):
raise KeyError
except (KeyError, TypeError):
_LOGGER.info("No videos found on page %s. Exiting.", page)
break
@@ -277,9 +323,9 @@ class Blink:
_LOGGER.debug("%s: %s is marked as deleted.", camera_name, address)
continue
clip_address = "{}{}".format(self.urls.base_url, address)
filename = "{}-{}".format(camera_name, created_at)
filename = "{}.mp4".format(slugify(filename))
clip_address = f"{self.urls.base_url}{address}"
filename = f"{camera_name}-{created_at}"
filename = f"{slugify(filename)}.mp4"
filename = os.path.join(path, filename)
if not debug:
@@ -287,15 +333,22 @@ class Blink:
_LOGGER.info("%s already exists, skipping...", filename)
continue
response = api.http_get(self, url=clip_address, stream=True, json=False)
response = api.http_get(
self,
url=clip_address,
stream=True,
json=False,
timeout=TIMEOUT_MEDIA,
)
with open(filename, "wb") as vidfile:
copyfileobj(response.raw, vidfile)
_LOGGER.info("Downloaded video to %s", filename)
else:
print(
("Camera: {}, Timestamp: {}, " "Address: {}, Filename: {}").format(
camera_name, created_at, address, filename
(
f"Camera: {camera_name}, Timestamp: {created_at}, "
"Address: {address}, Filename: {filename}"
)
)
+117 -31
View File
@@ -3,6 +3,7 @@
from shutil import copyfileobj
import logging
from blinkpy import api
from blinkpy.helpers.constants import TIMEOUT_MEDIA
_LOGGER = logging.getLogger(__name__)
@@ -29,6 +30,7 @@ class BlinkCamera:
self.last_record = None
self._cached_image = None
self._cached_video = None
self.camera_type = ""
@property
def attributes(self):
@@ -61,7 +63,10 @@ class BlinkCamera:
@property
def temperature_c(self):
"""Return temperature in celcius."""
return round((self.temperature - 32) / 9.0 * 5.0, 1)
try:
return round((self.temperature - 32) / 9.0 * 5.0, 1)
except TypeError:
return None
@property
def image_from_cache(self):
@@ -77,12 +82,44 @@ class BlinkCamera:
return self._cached_video
return None
@property
def arm(self):
"""Return arm status of camera."""
return self.motion_enabled
@arm.setter
def arm(self, value):
"""Set camera arm status."""
if value:
return api.request_motion_detection_enable(
self.sync.blink, self.network_id, self.camera_id
)
return api.request_motion_detection_disable(
self.sync.blink, self.network_id, self.camera_id
)
def record(self):
"""Initiate clip recording."""
return api.request_new_video(self.sync.blink, self.network_id, self.camera_id)
def get_media(self, media_type="image"):
"""Download media (image or video)."""
url = self.thumbnail
if media_type.lower() == "video":
url = self.clip
return api.http_get(
self.sync.blink, url=url, stream=True, json=False, timeout=TIMEOUT_MEDIA,
)
def snap_picture(self):
"""Take a picture with camera to create a new thumbnail."""
return api.request_new_image(self.sync.blink, self.network_id, self.camera_id)
def set_motion_detect(self, enable):
"""Set motion detection."""
_LOGGER.warning(
"Method is deprecated as of v0.16.0 and will be removed in a future version. Please use the BlinkCamera.arm property instead."
)
if enable:
return api.request_motion_detection_enable(
self.sync.blink, self.network_id, self.camera_id
@@ -93,18 +130,24 @@ class BlinkCamera:
def update(self, config, force_cache=False, **kwargs):
"""Update camera info."""
# force = kwargs.pop('force', False)
self.name = config["name"]
self.camera_id = str(config["id"])
self.network_id = str(config["network_id"])
self.serial = config["serial"]
self.motion_enabled = config["enabled"]
self.battery_voltage = config["battery_voltage"]
self.battery_state = config["battery_state"]
self.temperature = config["temperature"]
self.wifi_strength = config["wifi_strength"]
self.extract_config_info(config)
self.get_sensor_info()
self.update_images(config, force_cache=force_cache)
# Retrieve calibrated temperature from special endpoint
def extract_config_info(self, config):
"""Extract info from config."""
self.name = config.get("name", "unknown")
self.camera_id = str(config.get("id", "unknown"))
self.network_id = str(config.get("network_id", "unknown"))
self.serial = config.get("serial", None)
self.motion_enabled = config.get("enabled", "unknown")
self.battery_voltage = config.get("battery_voltage", None)
self.battery_state = config.get("battery_state", None)
self.temperature = config.get("temperature", None)
self.wifi_strength = config.get("wifi_strength", None)
def get_sensor_info(self):
"""Retrieve calibrated temperatue from special endpoint."""
resp = api.request_camera_sensors(
self.sync.blink, self.network_id, self.camera_id
)
@@ -114,20 +157,17 @@ class BlinkCamera:
self.temperature_calibrated = self.temperature
_LOGGER.warning("Could not retrieve calibrated temperature.")
# Check if thumbnail exists in config, if not try to
# get it from the homescreen info in the sync module
# otherwise set it to None and log an error
def update_images(self, config, force_cache=False):
"""Update images for camera."""
new_thumbnail = None
thumb_addr = None
if config["thumbnail"]:
if config.get("thumbnail", False):
thumb_addr = config["thumbnail"]
else:
_LOGGER.warning(
"Could not find thumbnail for camera %s", self.name, exc_info=True
)
_LOGGER.warning("Could not find thumbnail for camera %s", self.name)
if thumb_addr is not None:
new_thumbnail = "{}{}.jpg".format(self.sync.urls.base_url, thumb_addr)
new_thumbnail = f"{self.sync.urls.base_url}{thumb_addr}.jpg"
try:
self.motion_detected = self.sync.motion[self.name]
@@ -135,10 +175,12 @@ class BlinkCamera:
self.motion_detected = False
clip_addr = None
if self.name in self.sync.last_record:
try:
clip_addr = self.sync.last_record[self.name]["clip"]
self.last_record = self.sync.last_record[self.name]["time"]
self.clip = "{}{}".format(self.sync.urls.base_url, clip_addr)
self.clip = f"{self.sync.urls.base_url}{clip_addr}"
except KeyError:
pass
# If the thumbnail or clip have changed, update the cache
update_cached_image = False
@@ -151,13 +193,17 @@ class BlinkCamera:
update_cached_video = True
if new_thumbnail is not None and (update_cached_image or force_cache):
self._cached_image = api.http_get(
self.sync.blink, url=self.thumbnail, stream=True, json=False
)
self._cached_image = self.get_media()
if clip_addr is not None and (update_cached_video or force_cache):
self._cached_video = api.http_get(
self.sync.blink, url=self.clip, stream=True, json=False
)
self._cached_video = self.get_media(media_type="video")
def get_liveview(self):
"""Get livewview rtsps link."""
response = api.request_camera_liveview(
self.sync.blink, self.sync.network_id, self.camera_id
)
return response["server"]
def image_to_file(self, path):
"""
@@ -166,7 +212,7 @@ class BlinkCamera:
:param path: Path to write file
"""
_LOGGER.debug("Writing image from %s to %s", self.name, path)
response = self._cached_image
response = self.get_media()
if response.status_code == 200:
with open(path, "wb") as imgfile:
copyfileobj(response.raw, imgfile)
@@ -176,14 +222,54 @@ class BlinkCamera:
)
def video_to_file(self, path):
"""Write video to file.
"""
Write video to file.
:param path: Path to write file
"""
_LOGGER.debug("Writing video from %s to %s", self.name, path)
response = self._cached_video
response = self.get_media(media_type="video")
if response is None:
_LOGGER.error("No saved video exist for %s.", self.name)
return
with open(path, "wb") as vidfile:
copyfileobj(response.raw, vidfile)
class BlinkCameraMini(BlinkCamera):
"""Define a class for a Blink Mini camera."""
def __init__(self, sync):
"""Initialize a Blink Mini cameras."""
super().__init__(sync)
self.camera_type = "mini"
@property
def arm(self):
"""Return camera arm status."""
return self.sync.arm
@arm.setter
def arm(self, value):
"""Set camera arm status."""
_LOGGER.warning(
"Individual camera motion detection enable/disable for Blink Mini cameras is unsupported at this time."
)
def snap_picture(self):
"""Snap picture for a blink mini camera."""
url = f"{self.sync.urls.base_url}/api/v1/accounts/{self.sync.blink.account_id}/networks/{self.network_id}/owls/{self.camera_id}/thumbnail"
return api.http_post(self.sync.blink, url)
def get_sensor_info(self):
"""Get sensor info for blink mini camera."""
def get_liveview(self):
"""Get liveview link."""
url = f"{self.sync.urls.base_url}/api/v1/accounts/{self.sync.blink.account_id}/networks/{self.network_id}/owls/{self.camera_id}/liveview"
response = api.http_post(self.sync.blink, url)
server = response["server"]
server_split = server.split(":")
server_split[0] = "rtsps:"
link = "".join(server_split)
return link
+12 -12
View File
@@ -3,10 +3,10 @@
import os
MAJOR_VERSION = 0
MINOR_VERSION = 16
PATCH_VERSION = "0-rc0"
MINOR_VERSION = 17
PATCH_VERSION = 0
__version__ = "{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION)
__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 6, 0)
@@ -14,7 +14,7 @@ PROJECT_NAME = "blinkpy"
PROJECT_PACKAGE_NAME = "blinkpy"
PROJECT_LICENSE = "MIT"
PROJECT_AUTHOR = "Kevin Fronczak"
PROJECT_COPYRIGHT = " 2017, {}".format(PROJECT_AUTHOR)
PROJECT_COPYRIGHT = f" 2017, {PROJECT_AUTHOR}"
PROJECT_URL = "https://github.com/fronzbot/blinkpy"
PROJECT_EMAIL = "kfronczak@gmail.com"
PROJECT_DESCRIPTION = "A Blink camera Python library " "running on Python 3."
@@ -34,25 +34,22 @@ PROJECT_CLASSIFIERS = [
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Home Automation",
]
PROJECT_GITHUB_USERNAME = "fronzbot"
PROJECT_GITHUB_REPOSITORY = "blinkpy"
PYPI_URL = "https://pypi.python.org/pypi/{}".format(PROJECT_PACKAGE_NAME)
PYPI_URL = f"https://pypi.python.org/pypi/{PROJECT_PACKAGE_NAME}"
"""
URLS
"""
BLINK_URL = "immedia-semi.com"
DEFAULT_URL = "{}.{}".format("rest-prod", BLINK_URL)
BASE_URL = "https://{}".format(DEFAULT_URL)
LOGIN_ENDPOINT = "{}/api/v4/account/login".format(BASE_URL)
LOGIN_URLS = [
"{}/api/v4/account/login".format(BASE_URL),
"{}/api/v3/login".format(BASE_URL),
]
DEFAULT_URL = f"rest-prod.{BLINK_URL}"
BASE_URL = f"https://{DEFAULT_URL}"
LOGIN_ENDPOINT = f"{BASE_URL}/api/v5/account/login"
"""
Dictionaries
@@ -62,6 +59,7 @@ ONLINE = {"online": True, "offline": False}
"""
OTHER
"""
DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
DEVICE_ID = "Blinkpy"
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
DEFAULT_MOTION_INTERVAL = 1
@@ -69,3 +67,5 @@ DEFAULT_REFRESH = 30
MIN_THROTTLE_TIME = 2
SIZE_NOTIFICATION_KEY = 152
SIZE_UID = 16
TIMEOUT = 10
TIMEOUT_MEDIA = 90
+1 -1
View File
@@ -12,4 +12,4 @@ AUTH_TOKEN = (
)
REQUEST = (4, "Cannot perform request (get/post type incorrect)")
BLINK_ERRORS = [101, 400, 404]
BLINK_ERRORS = [400, 404]
+7 -7
View File
@@ -33,10 +33,13 @@ def json_save(data, file_name):
json.dump(data, json_file, indent=4)
def gen_uid(size):
def gen_uid(size, uid_format=False):
"""Create a random sring."""
full_token = secrets.token_hex(size)
return full_token[0:size]
if uid_format:
token = f"BlinkCamera_{secrets.token_hex(4)}-{secrets.token_hex(2)}-{secrets.token_hex(2)}-{secrets.token_hex(2)}-{secrets.token_hex(6)}"
else:
token = secrets.token_hex(size)
return token
def time_to_seconds(timestamp):
@@ -79,10 +82,7 @@ def prompt_login_data(data):
def validate_login_data(data):
"""Check for missing keys."""
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID))
data["notification_key"] = data.get(
"notification_key", gen_uid(const.SIZE_NOTIFICATION_KEY)
)
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID, uid_format=True))
data["device_id"] = data.get("device_id", const.DEVICE_ID)
return data
+123 -37
View File
@@ -4,7 +4,7 @@ import logging
from requests.structures import CaseInsensitiveDict
from blinkpy import api
from blinkpy.camera import BlinkCamera
from blinkpy.camera import BlinkCamera, BlinkCameraMini
from blinkpy.helpers.util import time_to_seconds
from blinkpy.helpers.constants import ONLINE
@@ -77,24 +77,15 @@ class BlinkSyncModule:
@arm.setter
def arm(self, value):
"""Arm or disarm system."""
"""Arm or disarm camera."""
if value:
return api.request_system_arm(self.blink, self.network_id)
return api.request_system_disarm(self.blink, self.network_id)
def start(self):
"""Initialize the system."""
response = api.request_syncmodule(self.blink, self.network_id)
try:
self.summary = response["syncmodule"]
self.network_id = self.summary["network_id"]
except (TypeError, KeyError):
_LOGGER.error(
("Could not retrieve sync module information " "with response: %s"),
response,
exc_info=True,
)
response = self.sync_initialize()
if not response:
return False
try:
@@ -102,32 +93,62 @@ class BlinkSyncModule:
self.serial = self.summary["serial"]
self.status = self.summary["status"]
except KeyError:
_LOGGER.error(
"Could not extract some sync module info: %s", response, exc_info=True
)
_LOGGER.error("Could not extract some sync module info: %s", response)
is_ok = self.get_network_info()
self.check_new_videos()
if not is_ok or not self.update_cameras():
return False
self.available = True
return True
def sync_initialize(self):
"""Initialize a sync module."""
response = api.request_syncmodule(self.blink, self.network_id)
try:
self.summary = response["syncmodule"]
self.network_id = self.summary["network_id"]
except (TypeError, KeyError):
_LOGGER.error(
"Could not retrieve sync module information with response: %s", response
)
return False
return response
def update_cameras(self, camera_type=BlinkCamera):
"""Update cameras from server."""
try:
for camera_config in self.camera_list:
if "name" not in camera_config:
break
blink_camera_type = camera_config.get("type", "")
name = camera_config["name"]
self.cameras[name] = BlinkCamera(self)
self.motion[name] = False
camera_info = self.get_camera_info(camera_config["id"])
owl_info = self.get_owl_info(name)
if blink_camera_type == "mini":
camera_type = BlinkCameraMini
self.cameras[name] = camera_type(self)
camera_info = self.get_camera_info(
camera_config["id"], owl_info=owl_info
)
self.cameras[name].update(camera_info, force_cache=True, force=True)
except KeyError:
_LOGGER.error(
"Could not create cameras instances for %s", self.name, exc_info=True
)
return False
if not is_ok:
except KeyError:
_LOGGER.error("Could not create camera instances for %s", self.name)
return False
self.available = True
return True
def get_owl_info(self, name):
"""Extract owl information."""
try:
for owl in self.blink.homescreen["owls"]:
if owl["name"] == name:
return owl
except (TypeError, KeyError):
pass
return None
def get_events(self, **kwargs):
"""Retrieve events from server."""
force = kwargs.pop("force", False)
@@ -135,28 +156,28 @@ class BlinkSyncModule:
try:
return response["event"]
except (TypeError, KeyError):
_LOGGER.error("Could not extract events: %s", response, exc_info=True)
_LOGGER.error("Could not extract events: %s", response)
return False
def get_camera_info(self, camera_id):
def get_camera_info(self, camera_id, **kwargs):
"""Retrieve camera information."""
owl = kwargs.get("owl_info", None)
if owl is not None:
return owl
response = api.request_camera_info(self.blink, self.network_id, camera_id)
try:
return response["camera"][0]
except (TypeError, KeyError):
_LOGGER.error("Could not extract camera info: %s", response, exc_info=True)
return []
_LOGGER.error("Could not extract camera info: %s", response)
return {}
def get_network_info(self):
"""Retrieve network status."""
is_errored = False
self.network_info = api.request_network_status(self.blink, self.network_id)
self.network_info = api.request_network_update(self.blink, self.network_id)
try:
is_errored = self.network_info["network"]["sync_module_error"]
except KeyError:
is_errored = True
if is_errored:
if self.network_info["network"]["sync_module_error"]:
raise KeyError
except (TypeError, KeyError):
self.available = False
return False
return True
@@ -168,7 +189,9 @@ class BlinkSyncModule:
self.check_new_videos()
for camera_name in self.cameras.keys():
camera_id = self.cameras[camera_name].camera_id
camera_info = self.get_camera_info(camera_id)
camera_info = self.get_camera_info(
camera_id, owl_info=self.get_owl_info(camera_name)
)
self.cameras[camera_name].update(camera_info, force_cache=force_cache)
self.available = True
@@ -208,3 +231,66 @@ class BlinkSyncModule:
def check_new_video_time(self, timestamp):
"""Check if video has timestamp since last refresh."""
return time_to_seconds(timestamp) > self.blink.last_refresh
class BlinkOwl(BlinkSyncModule):
"""Representation of a sync-less device."""
def __init__(self, blink, name, network_id, response):
"""Initialize a sync-less object."""
cameras = [{"name": name, "id": response["id"]}]
super().__init__(blink, name, network_id, cameras)
self.sync_id = response["id"]
self.serial = response["serial"]
self.status = response["enabled"]
if not self.serial:
self.serial = f"{network_id}-{self.sync_id}"
def sync_initialize(self):
"""Initialize a sync-less module."""
self.summary = {
"id": self.sync_id,
"name": self.name,
"serial": self.serial,
"status": self.status,
"onboarded": True,
"account_id": self.blink.account_id,
"network_id": self.network_id,
}
return self.summary
def update_cameras(self, camera_type=BlinkCameraMini):
"""Update sync-less cameras."""
return super().update_cameras(camera_type=BlinkCameraMini)
def get_camera_info(self, camera_id, **kwargs):
"""Retrieve camera information."""
try:
for owl in self.blink.homescreen["owls"]:
if owl["name"] == self.name:
self.status = owl["enabled"]
return owl
except (TypeError, KeyError):
pass
return None
def get_network_info(self):
"""Get network info for sync-less module."""
return True
@property
def network_info(self):
"""Format owl response to resemble sync module."""
return {
"network": {
"id": self.network_id,
"name": self.name,
"armed": self.status,
"sync_module_error": False,
"account_id": self.blink.account_id,
}
}
@network_info.setter
def network_info(self, value):
"""Set network_info property."""
+5 -3
View File
@@ -4,10 +4,12 @@ coverage:
status:
project:
default:
target: 80%
threshold: 2%
patch:
default:
target: 60%
threshold: 5%
comment: true
require_ci_to_pass: yes
range: 65..90
round: down
precision: 1
+77
View File
@@ -0,0 +1,77 @@
"""Login testing script."""
import sys
import os
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load, json_save
save_session = False
print("")
print("Blink Login Debug Script ...")
print(" ... Loading previous session information.")
cwd = os.getcwd()
print(f" ... Looking in {cwd}.")
session_path = os.path.join(cwd, ".session_debug")
session = json_load(session_path)
try:
auth_file = session["file"]
except (TypeError, KeyError):
print(" ... Please input location of auth file")
auth_file = input(" Must contain username and password: ")
save_session = True
data = json_load(auth_file)
if data is None:
print(f" ... Please fix file contents of {auth_file}.")
print(" ... Exiting.")
sys.exit(1)
try:
username = data["username"]
password = data["password"]
except KeyError:
print(f" ... File contents of {auth_file} incorrect.")
print(" ... Require username and password at minimum.")
print(" ... Exiting.")
sys.exit(1)
if save_session:
print(f" ... Saving session file to {session_path}.")
json_save({"file": auth_file}, session_path)
blink = Blink()
auth = Auth(data)
blink.auth = auth
print(" ... Starting Blink.")
print("")
blink.start()
print("")
print(" ... Printing login response.")
print("")
print(blink.auth.login_response)
print("")
print(" ... Printing login attributes.")
print("")
print(blink.auth.login_attributes)
print("")
input(" ... Press any key to continue: ")
print(" ... Deactivating auth token.")
blink.auth.token = "foobar"
print(f"\t - blink.auth.token = {blink.auth.token}")
print(" ... Attempting login.")
print("")
blink.start()
print("")
print(" ... Printing login response.")
print("")
print(blink.auth.login_response)
print("")
print(" ... Printing login attributes.")
print("")
print(blink.auth.login_attributes)
print("")
rint(" ... Done.")
print("")
+1
View File
@@ -0,0 +1 @@
../CHANGES.rst
+1
View File
@@ -0,0 +1 @@
../CONTRIBUTING.rst
+104
View File
@@ -0,0 +1,104 @@
=======================
Advanced Library Usage
=======================
Usage of this library was designed with the `Home Assistant <https://home-assistant.io>`__ project in mind. With that said, this library is flexible to be used in other scripts where advanced usage not covered in the Quick Start guide may be required. This usage guide will attempt to cover as many use cases as possible.
Throttling
--------------
In general, attempting too many requests to the Blink servers will result in your account being throttled. Where possible, adding a delay between calls is ideal. For use cases where this is not an acceptable solution, the ``blinkpy.helpers.util`` module contains a ``Throttle`` class that can be used as a decorator for calls. There are many examples of usage within the ``blinkpy.api`` module. A simple example of usage is covered below, where the decorated method is prevented from executing again until 10s has passed. Note that if the method call is throttled by the decorator, the method will return `None`.
.. code:: python
from blinkpy.helpers.util import Throttle
@Throttle(seconds=10)
def my_method(*args):
"""Some method to be throttled."""
return True
Custom Sessions
-----------------
By default, the ``blink.auth.Auth`` class creates its own websession via its ``create_session`` method. This is done when the class is initialized and is accessible via the ``Auth.session`` property. To override with a custom websession, the following code can accomplish that:
.. code:: python
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
blink = Blink()
blink.auth = Auth()
blink.auth.session = YourCustomSession
Custom Retry Logic
--------------------
The built-in auth session via the ``create_session`` method allows for customizable retry intervals and conditions. These parameters are:
- retries
- backoff
- retry_list
``retries`` is the total number of retry attempts that each http request can do before timing out. ``backoff`` is a parameter that allows for non-linear retry times such that the time between retries is backoff*(2^(retries) - 1). ``retry_list`` is simply a list of status codes to force a retry. By default ``retries=3``, ``backoff=1``, and ``retry_list=[429, 500, 502, 503, 504]``. To override them, you need to add you overrides to a dictionary and use that to create a new session with the ``opts`` variable in the ``create_session`` method. The following example can serve as a guide where only the number of retries and backoff factor are overridden:
.. code:: python
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
blink = Blink()
blink.auth = Auth()
opts = {"retries": 10, "backoff": 2}
blink.auth.session = blink.auth.create_session(opts=opts)
Custom HTTP requests
---------------------
In addition to custom sessions, custom blink server requests can be performed. This give you the ability to bypass the built-in ``Auth.query`` method. It also allows flexibility by giving you the option to pass your own url, rather than be limited to what is currently implemented in the ``blinkpy.api`` module.
**Send custom url**
This prepares a standard "GET" request.
.. code:: python
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
blink = Blink()
blink.auth = Auth()
url = some_api_endpoint_string
request = blink.auth.prepare_request(url, blink.auth.header, None, "get")
response = blink.auth.session.send(request)
**Overload query method**
Another option is to create your own ``Auth`` class with a custom ``query`` method to avoid the built-in response checking. This allows you to use the built in ``blinkpy.api`` endpoints, but also gives you flexibility to send your own urls.
.. code:: python
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy import api
class CustomAuth(Auth):
def query(
self,
url=None,
data=None,
headers=self.header,
reqtype="get",
stream=False,
json_resp=True,
**kwargs
):
req = self.prepare_request(url, headers, data, reqtype)
return self.session.send(req, stream=stream)
blink = blink.Blink()
blink.auth = CustomAuth()
# Send custom GET query
response = blink.auth.query(url=some_custom_url)
# Call built-in networks api endpoint
response = api.request_networks(blink)
-17
View File
@@ -1,17 +0,0 @@
.. _core_module:
Blinkpy
----------------------
.. automodule:: blinkpy.blinkpy
:members:
.. automodule:: blinkpy.sync_module
:members:
.. automodule:: blinkpy.camera
:members:
.. automodule:: blinkpy.helpers.util
:members:
-6
View File
@@ -1,6 +0,0 @@
API Reference
----------------------
.. automodule:: blinkpy.api
:members:
+6 -2
View File
@@ -7,12 +7,16 @@ Welcome to blinkpy's documentation!
===================================
.. toctree::
:maxdepth: 2
:maxdepth: 1
:caption: Contents:
:glob:
README
api/*
advanced
CONTRIBUTING
modules/*
CHANGES
Indices and tables
==================
+41
View File
@@ -0,0 +1,41 @@
.. _core_module:
===========================
Blinkpy Library Reference
===========================
blinkpy.py
-----------
.. automodule:: blinkpy.blinkpy
:members:
auth.py
--------
.. automodule:: blinkpy.auth
:members:
sync_module.py
----------------
.. automodule:: blinkpy.sync_module
:members:
camera.py
-----------
.. automodule:: blinkpy.camera
:members:
api.py
---------
.. automodule:: blinkpy.api
:members:
helpers/util.py
----------------
.. automodule:: blinkpy.helpers.util
:members:
+3 -4
View File
@@ -1,4 +1,3 @@
python-dateutil~=2.8.1
requests~=2.23.0
python-slugify~=4.0.0
testtools==2.4.0
python-dateutil>=2.8.1
requests>=2.24.0
python-slugify>=4.0.1
+12 -11
View File
@@ -1,13 +1,14 @@
black==19.10b0
coverage==5.1
flake8==3.8.1
coverage==5.4
flake8==3.8.4
flake8-docstrings==1.5.0
pre-commit==2.4.0
pylint==2.5.2
pydocstyle==5.0.2
pytest==5.4.2
pytest-cov==2.8.1
pytest-sugar==0.9.3
pytest-timeout==1.3.4
restructuredtext-lint==1.3.0
pygments==2.6.1
pre-commit==2.10.1
pylint==2.6.0
pydocstyle==5.1.1
pytest==6.2.2
pytest-cov==2.11.1
pytest-sugar==0.9.4
pytest-timeout==1.4.2
restructuredtext-lint==1.3.2
pygments==2.8.0
testtools>=2.4.0
+16 -13
View File
@@ -3,23 +3,26 @@
from os.path import abspath, dirname
from setuptools import setup, find_packages
from blinkpy.helpers.constants import (
__version__, PROJECT_PACKAGE_NAME, PROJECT_LICENSE, PROJECT_URL,
PROJECT_EMAIL, PROJECT_DESCRIPTION, PROJECT_CLASSIFIERS, PROJECT_AUTHOR,
__version__,
PROJECT_PACKAGE_NAME,
PROJECT_LICENSE,
PROJECT_URL,
PROJECT_EMAIL,
PROJECT_DESCRIPTION,
PROJECT_CLASSIFIERS,
PROJECT_AUTHOR,
)
PROJECT_VERSION = __version__
THIS_DIR = abspath(dirname(__file__))
REQUIRES = [
"python-dateutil~=2.8.1",
"requests~=2.23.0",
"python-slugify~=4.0.0",
]
with open(f"{THIS_DIR}/requirements.txt") as req_file:
REQUIRES = [line.rstrip() for line in req_file]
PACKAGES = find_packages(exclude=['tests*', 'docs'])
PACKAGES = find_packages(exclude=["tests*", "docs"])
with open('{}/README.rst'.format(THIS_DIR), encoding='utf-8') as readme_file:
with open("{}/README.rst".format(THIS_DIR), encoding="utf-8") as readme_file:
LONG_DESCRIPTION = readme_file.read()
setup(
@@ -31,11 +34,11 @@ setup(
author_email=PROJECT_EMAIL,
license=PROJECT_LICENSE,
url=PROJECT_URL,
platforms='any',
py_modules=['blinkpy'],
platforms="any",
py_modules=["blinkpy"],
packages=PACKAGES,
include_package_data=True,
install_requires=REQUIRES,
test_suite='tests',
classifiers=PROJECT_CLASSIFIERS
test_suite="tests",
classifiers=PROJECT_CLASSIFIERS,
)
+1
View File
@@ -9,6 +9,7 @@ class MockResponse:
self.json_data = json_data
self.status_code = status_code
self.raw_data = raw_data
self.reason = "foobar"
def json(self):
"""Return json data from get_request."""
+104 -12
View File
@@ -3,7 +3,13 @@
import unittest
from unittest import mock
from requests import exceptions
from blinkpy.auth import Auth, LoginError, TokenRefreshFailed
from blinkpy.auth import (
Auth,
LoginError,
TokenRefreshFailed,
BlinkBadResponse,
UnauthorizedError,
)
import blinkpy.helpers.constants as const
import tests.mock_responses as mresp
@@ -36,7 +42,6 @@ class TestAuth(unittest.TestCase):
"username": "foo",
"password": "bar",
"uid": 1234,
"notification_key": 1234,
"device_id": const.DEVICE_ID,
}
self.assertDictEqual(auth.data, expected_data)
@@ -56,7 +61,6 @@ class TestAuth(unittest.TestCase):
"username": "foo",
"password": "bar",
"uid": 1234,
"notification_key": 1234,
"device_id": const.DEVICE_ID,
}
self.assertDictEqual(auth.data, expected_data)
@@ -86,25 +90,47 @@ class TestAuth(unittest.TestCase):
def test_bad_response_code(self):
"""Check bad response code from server."""
self.auth.is_errored = False
fake_resp = mresp.MockResponse({"code": 404}, 404)
with self.assertRaises(exceptions.ConnectionError):
self.auth.validate_response(fake_resp, True)
self.assertTrue(self.auth.is_errored)
self.auth.is_errored = False
fake_resp = mresp.MockResponse({"code": 101}, 401)
with self.assertRaises(UnauthorizedError):
self.auth.validate_response(fake_resp, True)
self.assertTrue(self.auth.is_errored)
def test_good_response_code(self):
"""Check good response code from server."""
fake_resp = mresp.MockResponse({"foo": "bar"}, 200)
self.auth.is_errored = True
self.assertEqual(self.auth.validate_response(fake_resp, True), {"foo": "bar"})
self.assertFalse(self.auth.is_errored)
def test_response_not_json(self):
"""Check response when not json."""
fake_resp = "foobar"
self.auth.is_errored = True
self.assertEqual(self.auth.validate_response(fake_resp, False), "foobar")
self.assertFalse(self.auth.is_errored)
def test_response_bad_json(self):
"""Check response when not json but expecting json."""
self.auth.is_errored = False
with self.assertRaises(BlinkBadResponse):
self.auth.validate_response(None, True)
self.assertTrue(self.auth.is_errored)
def test_header(self):
"""Test header data."""
self.auth.token = "bar"
self.auth.host = "foo"
expected_header = {"Host": "foo", "TOKEN_AUTH": "bar"}
expected_header = {
"TOKEN_AUTH": "bar",
"user-agent": const.DEFAULT_USER_AGENT,
"content-type": "application/json",
}
self.assertDictEqual(self.auth.header, expected_header)
def test_header_no_token(self):
@@ -126,17 +152,19 @@ class TestAuth(unittest.TestCase):
"""Test login handling when bad response."""
fake_resp = mresp.MockResponse({"foo": "bar"}, 404)
mock_req.return_value = fake_resp
self.auth.is_errored = False
with self.assertRaises(LoginError):
self.auth.login()
with self.assertRaises(TokenRefreshFailed):
self.auth.refresh_token()
self.assertTrue(self.auth.is_errored)
@mock.patch("blinkpy.auth.Auth.login")
def test_refresh_token(self, mock_login):
"""Test refresh token method."""
mock_login.return_value = {
"region": {"tier": "test"},
"authtoken": {"authtoken": "foobar"},
"client": {"id": 1234},
"account": {"id": 5678},
"account": {"account_id": 5678, "client_id": 1234, "tier": "test"},
"auth": {"token": "foobar"},
}
self.assertTrue(self.auth.refresh_token())
self.assertEqual(self.auth.region_id, "test")
@@ -148,20 +176,29 @@ class TestAuth(unittest.TestCase):
def test_refresh_token_failed(self, mock_login):
"""Test refresh token failed."""
mock_login.return_value = {}
self.auth.is_errored = False
with self.assertRaises(TokenRefreshFailed):
self.auth.refresh_token()
self.assertTrue(self.auth.is_errored)
def test_check_key_required(self):
"""Check key required method."""
self.auth.login_response = {}
self.assertFalse(self.auth.check_key_required())
self.auth.login_response = {"client": {"verification_required": False}}
self.auth.login_response = {"account": {"client_verification_required": False}}
self.assertFalse(self.auth.check_key_required())
self.auth.login_response = {"client": {"verification_required": True}}
self.auth.login_response = {"account": {"client_verification_required": True}}
self.assertTrue(self.auth.check_key_required())
@mock.patch("blinkpy.auth.api.request_logout")
def test_logout(self, mock_req):
"""Test logout method."""
mock_blink = MockBlink(None)
mock_req.return_value = True
self.assertTrue(self.auth.logout(mock_blink))
@mock.patch("blinkpy.auth.api.request_verify")
def test_send_auth_key(self, mock_req):
"""Check sending of auth key."""
@@ -192,10 +229,65 @@ class TestAuth(unittest.TestCase):
def test_query_retry(self, mock_refresh, mock_validate):
"""Check handling of request retry."""
self.auth.session = MockSession()
mock_validate.side_effect = [TokenRefreshFailed, "foobar"]
mock_validate.side_effect = [UnauthorizedError, "foobar"]
mock_refresh.return_value = True
self.assertEqual(self.auth.query(url="http://example.com"), "foobar")
@mock.patch("blinkpy.auth.Auth.validate_response")
@mock.patch("blinkpy.auth.Auth.refresh_token")
def test_query_retry_failed(self, mock_refresh, mock_validate):
"""Check handling of failed retry request."""
self.auth.session = MockSession()
mock_validate.side_effect = [UnauthorizedError, BlinkBadResponse]
mock_refresh.return_value = True
self.assertEqual(self.auth.query(url="http://example.com"), None)
mock_validate.side_effect = [UnauthorizedError, TokenRefreshFailed]
self.assertEqual(self.auth.query(url="http://example.com"), None)
def test_default_session(self):
"""Test default session creation."""
sess = self.auth.create_session()
adapter = sess.adapters["https://"]
self.assertEqual(adapter.max_retries.total, 3)
self.assertEqual(adapter.max_retries.backoff_factor, 1)
self.assertEqual(
adapter.max_retries.status_forcelist, [429, 500, 502, 503, 504]
)
def test_custom_session_full(self):
"""Test full custom session creation."""
opts = {"backoff": 2, "retries": 10, "retry_list": [404]}
sess = self.auth.create_session(opts=opts)
adapter = sess.adapters["https://"]
self.assertEqual(adapter.max_retries.total, 10)
self.assertEqual(adapter.max_retries.backoff_factor, 2)
self.assertEqual(adapter.max_retries.status_forcelist, [404])
def test_custom_session_partial(self):
"""Test partial custom session creation."""
opts1 = {"backoff": 2}
opts2 = {"retries": 5}
opts3 = {"retry_list": [101, 202]}
sess1 = self.auth.create_session(opts=opts1)
sess2 = self.auth.create_session(opts=opts2)
sess3 = self.auth.create_session(opts=opts3)
adapt1 = sess1.adapters["https://"]
adapt2 = sess2.adapters["https://"]
adapt3 = sess3.adapters["https://"]
self.assertEqual(adapt1.max_retries.total, 3)
self.assertEqual(adapt1.max_retries.backoff_factor, 2)
self.assertEqual(adapt1.max_retries.status_forcelist, [429, 500, 502, 503, 504])
self.assertEqual(adapt2.max_retries.total, 5)
self.assertEqual(adapt2.max_retries.backoff_factor, 1)
self.assertEqual(adapt2.max_retries.status_forcelist, [429, 500, 502, 503, 504])
self.assertEqual(adapt3.max_retries.total, 3)
self.assertEqual(adapt3.max_retries.backoff_factor, 1)
self.assertEqual(adapt3.max_retries.status_forcelist, [101, 202])
class MockSession:
"""Object to mock a session."""
+23 -16
View File
@@ -5,29 +5,23 @@ import logging
from blinkpy import blinkpy
from blinkpy.sync_module import BlinkSyncModule
from blinkpy.camera import BlinkCamera
from blinkpy.helpers.util import get_time, BlinkURLHandler
class MockSyncModule(BlinkSyncModule):
"""Mock http requests from sync module."""
"""Mock blink sync module object."""
def __init__(self, blink, header):
"""Create mock sync module instance."""
super().__init__(blink, header, network_id=None, camera_list=None)
self.blink = blink
self.header = header
self.return_value = None
self.return_value2 = None
def get_network_info(self):
"""Mock network info method."""
return True
def http_get(self, url, stream=False, json=True):
"""Mock get request."""
if stream and self.return_value2 is not None:
return self.return_value2
return self.return_value
def http_post(self, url):
"""Mock post request."""
return self.return_value
class MockCamera(BlinkCamera):
"""Mock blink camera object."""
def update(self, config, force_cache=False, **kwargs):
"""Mock camera update method."""
class TestBlinkFunctions(unittest.TestCase):
@@ -121,3 +115,16 @@ class TestBlinkFunctions(unittest.TestCase):
with self.assertLogs() as dl_log:
blink.download_videos("/tmp", camera="bar", stop=2)
self.assertEqual(dl_log.output, expected_log)
@mock.patch("blinkpy.blinkpy.api.request_network_update")
@mock.patch("blinkpy.auth.Auth.query")
def test_refresh(self, mock_req, mock_update):
"""Test ability to refresh system."""
mock_update.return_value = {"network": {"sync_module_error": False}}
mock_req.return_value = None
self.blink.last_refresh = 0
self.blink.available = True
self.blink.sync["foo"] = MockSyncModule(self.blink, "foo", 1, [])
self.blink.cameras = {"bar": MockCamera(self.blink.sync)}
self.blink.sync["foo"].cameras = self.blink.cameras
self.assertTrue(self.blink.refresh())
+117 -10
View File
@@ -9,6 +9,7 @@ any communication related errors at startup.
import unittest
from unittest import mock
from blinkpy.blinkpy import Blink, BlinkSetupError
from blinkpy.sync_module import BlinkOwl
from blinkpy.helpers.constants import __version__
@@ -67,8 +68,8 @@ class TestBlinkSetup(unittest.TestCase):
self.assertEqual(self.blink.last_refresh, None)
with mock.patch(
"blinkpy.sync_module.BlinkSyncModule.refresh", return_value=True
):
self.blink.refresh()
), mock.patch("blinkpy.blinkpy.Blink.get_homescreen", return_value=True):
self.blink.refresh(force=True)
self.assertEqual(self.blink.last_refresh, now)
self.assertEqual(self.blink.check_if_ok_to_update(), False)
@@ -81,14 +82,21 @@ class TestBlinkSetup(unittest.TestCase):
self.assertEqual(self.blink.sync["TEST"], 1234)
self.assertEqual(self.blink.sync["tEsT"], 1234)
@mock.patch("blinkpy.api.request_camera_usage")
@mock.patch("blinkpy.api.request_homescreen")
def test_setup_cameras(self, mock_home):
def test_setup_cameras(self, mock_home, mock_req):
"""Check retrieval of camera information."""
mock_home.return_value = {
"cameras": [
{"name": "foo", "network_id": 1234, "id": 5678},
{"name": "bar", "network_id": 1234, "id": 5679},
{"name": "test", "network_id": 4321, "id": 0000},
mock_home.return_value = {}
mock_req.return_value = {
"networks": [
{
"network_id": 1234,
"cameras": [
{"id": 5678, "name": "foo"},
{"id": 5679, "name": "bar"},
],
},
{"network_id": 4321, "cameras": [{"id": 0000, "name": "test"}]},
]
}
result = self.blink.setup_camera_list()
@@ -100,12 +108,15 @@ class TestBlinkSetup(unittest.TestCase):
},
)
@mock.patch("blinkpy.api.request_homescreen")
@mock.patch("blinkpy.api.request_camera_usage")
def test_setup_cameras_failure(self, mock_home):
"""Check that on failure we raise a setup error."""
mock_home.return_value = {}
with self.assertRaises(BlinkSetupError):
self.blink.setup_camera_list()
mock_home.return_value = None
with self.assertRaises(BlinkSetupError):
self.blink.setup_camera_list()
def test_setup_urls(self):
"""Check setup of URLS."""
@@ -132,6 +143,9 @@ class TestBlinkSetup(unittest.TestCase):
mock_networks.return_value = {}
with self.assertRaises(BlinkSetupError):
self.blink.setup_networks()
mock_networks.return_value = None
with self.assertRaises(BlinkSetupError):
self.blink.setup_networks()
@mock.patch("blinkpy.blinkpy.Auth.send_auth_key")
def test_setup_prompt_2fa(self, mock_key):
@@ -149,10 +163,12 @@ class TestBlinkSetup(unittest.TestCase):
@mock.patch("blinkpy.blinkpy.Blink.setup_camera_list")
@mock.patch("blinkpy.api.request_networks")
def test_setup_post_verify(self, mock_networks, mock_camera):
@mock.patch("blinkpy.blinkpy.Blink.setup_owls")
def test_setup_post_verify(self, mock_owl, mock_networks, mock_camera):
"""Test setup after verification."""
self.blink.available = False
self.blink.key_required = True
mock_owl.return_value = True
mock_networks.return_value = {
"summary": {"foo": {"onboarded": False, "name": "bar"}}
}
@@ -181,6 +197,97 @@ class TestBlinkSetup(unittest.TestCase):
self.assertEqual(combined["fizz"], "buzz")
self.assertEqual(combined["bar"], "foo")
@mock.patch("blinkpy.blinkpy.BlinkOwl.start")
def test_initialize_blink_minis(self, mock_start):
"""Test blink mini initialization."""
mock_start.return_value = True
self.blink.homescreen = {
"owls": [
{
"enabled": False,
"id": 1,
"name": "foo",
"network_id": 2,
"onboarded": True,
"status": "online",
"thumbnail": "/foo/bar",
"serial": "1234",
},
{
"enabled": True,
"id": 3,
"name": "bar",
"network_id": 4,
"onboarded": True,
"status": "online",
"thumbnail": "/foo/bar",
"serial": "abcd",
},
]
}
self.blink.sync = {}
self.blink.setup_owls()
self.assertEqual(self.blink.sync["foo"].__class__, BlinkOwl)
self.assertEqual(self.blink.sync["bar"].__class__, BlinkOwl)
self.assertEqual(self.blink.sync["foo"].arm, False)
self.assertEqual(self.blink.sync["bar"].arm, True)
self.assertEqual(self.blink.sync["foo"].name, "foo")
self.assertEqual(self.blink.sync["bar"].name, "bar")
def test_blink_mini_cameras_returned(self):
"""Test that blink mini cameras are found if attached to sync module."""
self.blink.network_ids = ["1234"]
self.blink.homescreen = {
"owls": [
{
"id": 1,
"name": "foo",
"network_id": 1234,
"onboarded": True,
"enabled": True,
"status": "online",
"thumbnail": "/foo/bar",
"serial": "abc123",
}
]
}
result = self.blink.setup_owls()
self.assertEqual(self.blink.network_ids, ["1234"])
self.assertEqual(
result, [{"1234": {"name": "foo", "id": "1234", "type": "mini"}}]
)
self.blink.no_owls = True
self.blink.network_ids = []
self.blink.get_homescreen()
result = self.blink.setup_owls()
self.assertEqual(self.blink.network_ids, [])
self.assertEqual(result, [])
@mock.patch("blinkpy.api.request_camera_usage")
def test_blink_mini_attached_to_sync(self, mock_usage):
"""Test that blink mini cameras are properly attached to sync module."""
self.blink.network_ids = ["1234"]
self.blink.homescreen = {
"owls": [
{
"id": 1,
"name": "foo",
"network_id": 1234,
"onboarded": True,
"enabled": True,
"status": "online",
"thumbnail": "/foo/bar",
"serial": "abc123",
}
]
}
mock_usage.return_value = {"networks": [{"cameras": [], "network_id": 1234}]}
result = self.blink.setup_camera_list()
self.assertEqual(
result, {"1234": [{"name": "foo", "id": "1234", "type": "mini"}]}
)
class MockSync:
"""Mock sync module class."""
+36 -5
View File
@@ -11,7 +11,7 @@ from unittest import mock
from blinkpy.blinkpy import Blink
from blinkpy.helpers.util import BlinkURLHandler
from blinkpy.sync_module import BlinkSyncModule
from blinkpy.camera import BlinkCamera
from blinkpy.camera import BlinkCamera, BlinkCameraMini
CAMERA_CFG = {
@@ -117,10 +117,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
"WARNING:blinkpy.camera:Could not retrieve calibrated "
"temperature."
),
(
"WARNING:blinkpy.camera:Could not find thumbnail for camera new"
"\nNoneType: None"
),
("WARNING:blinkpy.camera:Could not find thumbnail for camera new"),
],
)
@@ -144,6 +141,15 @@ class TestBlinkCameraSetup(unittest.TestCase):
self.assertEqual(self.camera.clip, None)
self.assertEqual(self.camera.video_from_cache, None)
def test_camera_arm_status(self, mock_resp):
"""Test arming and disarming camera."""
self.camera.motion_enabled = None
self.assertFalse(self.camera.arm)
self.camera.motion_enabled = False
self.assertFalse(self.camera.arm)
self.camera.motion_enabled = True
self.assertTrue(self.camera.arm)
@mock.patch("blinkpy.camera.api.request_motion_detection_enable")
@mock.patch("blinkpy.camera.api.request_motion_detection_disable")
def test_motion_detection_enable_disable(self, mock_dis, mock_en, mock_rep):
@@ -152,3 +158,28 @@ class TestBlinkCameraSetup(unittest.TestCase):
mock_en.return_value = "enable"
self.assertEqual(self.camera.set_motion_detect(True), "enable")
self.assertEqual(self.camera.set_motion_detect(False), "disable")
def test_missing_attributes(self, mock_resp):
"""Test that attributes return None if missing."""
self.camera.temperature = None
self.camera.serial = None
attr = self.camera.attributes
self.assertEqual(attr["serial"], None)
self.assertEqual(attr["temperature"], None)
self.assertEqual(attr["temperature_c"], None)
def test_mini_missing_attributes(self, mock_resp):
"""Test that attributes return None if missing."""
camera = BlinkCameraMini(self.blink.sync)
self.blink.sync.network_id = None
self.blink.sync.name = None
attr = camera.attributes
for key in attr:
self.assertEqual(attr[key], None)
def test_camera_stream(self, mock_resp):
"""Test that camera stream returns correct url."""
mock_resp.return_value = {"server": "rtsps://foo.bar"}
mini_camera = BlinkCameraMini(self.blink.sync["test"])
self.assertEqual(self.camera.get_liveview(), "rtsps://foo.bar")
self.assertEqual(mini_camera.get_liveview(), "rtsps://foo.bar")
+41 -6
View File
@@ -4,8 +4,8 @@ from unittest import mock
from blinkpy.blinkpy import Blink
from blinkpy.helpers.util import BlinkURLHandler
from blinkpy.sync_module import BlinkSyncModule
from blinkpy.camera import BlinkCamera
from blinkpy.sync_module import BlinkSyncModule, BlinkOwl
from blinkpy.camera import BlinkCamera, BlinkCameraMini
@mock.patch("blinkpy.auth.Auth.query")
@@ -78,13 +78,31 @@ class TestBlinkSyncModule(unittest.TestCase):
self.assertEqual(self.blink.sync["test"].get_camera_info("1234"), "foobar")
def test_get_camera_info_fail(self, mock_resp):
"""Test hadnling of failed get camera info function."""
"""Test handling of failed get camera info function."""
mock_resp.return_value = None
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), [])
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), {})
mock_resp.return_value = {}
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), [])
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), {})
mock_resp.return_value = {"camera": None}
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), [])
self.assertEqual(self.blink.sync["test"].get_camera_info("1"), {})
def test_get_network_info(self, mock_resp):
"""Test network retrieval."""
mock_resp.return_value = {"network": {"sync_module_error": False}}
self.assertTrue(self.blink.sync["test"].get_network_info())
mock_resp.return_value = {"network": {"sync_module_error": True}}
self.assertFalse(self.blink.sync["test"].get_network_info())
def test_get_network_info_failure(self, mock_resp):
"""Test failed network retrieval."""
mock_resp.return_value = {}
self.blink.sync["test"].available = True
self.assertFalse(self.blink.sync["test"].get_network_info())
self.assertFalse(self.blink.sync["test"].available)
self.blink.sync["test"].available = True
mock_resp.return_value = None
self.assertFalse(self.blink.sync["test"].get_network_info())
self.assertFalse(self.blink.sync["test"].available)
def test_check_new_videos_startup(self, mock_resp):
"""Test that check_new_videos does not block startup."""
@@ -257,3 +275,20 @@ class TestBlinkSyncModule(unittest.TestCase):
"""Test sync attributes."""
self.assertEqual(self.blink.sync["test"].attributes["name"], "test")
self.assertEqual(self.blink.sync["test"].attributes["network_id"], "1234")
def test_owl_start(self, mock_resp):
"""Test owl camera instantiation."""
response = {
"name": "foo",
"id": 2,
"serial": "foobar123",
"enabled": True,
"network_id": 1,
"thumbnail": "/foo/bar",
}
self.blink.last_refresh = None
self.blink.homescreen = {"owls": [response]}
owl = BlinkOwl(self.blink, "foo", 1234, response)
self.assertTrue(owl.start())
self.assertTrue("foo" in owl.cameras)
self.assertEqual(owl.cameras["foo"].__class__, BlinkCameraMini)
+36 -1
View File
@@ -3,7 +3,7 @@
import unittest
from unittest import mock
import time
from blinkpy.helpers.util import json_load, Throttle, time_to_seconds
from blinkpy.helpers.util import json_load, Throttle, time_to_seconds, gen_uid
class TestUtil(unittest.TestCase):
@@ -67,6 +67,25 @@ class TestUtil(unittest.TestCase):
self.assertEqual(throttled(), True)
self.assertEqual(throttled(), None)
def test_throttle_multiple_objects(self):
"""Test that function is throttled even if called by multiple objects."""
@Throttle(seconds=5)
def test_throttle_method():
return True
class Tester:
"""A tester class for throttling."""
def test(self):
"""Test function for throttle."""
return test_throttle_method()
tester1 = Tester()
tester2 = Tester()
self.assertEqual(tester1.test(), True)
self.assertEqual(tester2.test(), None)
def test_throttle_on_two_methods(self):
"""Test that throttle works for multiple methods."""
@@ -113,3 +132,19 @@ class TestUtil(unittest.TestCase):
self.assertEqual(json_load("fake.file"), None)
with mock.patch("builtins.open", mock.mock_open(read_data="")):
self.assertEqual(json_load("fake.file"), None)
def test_gen_uid(self):
"""Test gen_uid formatting."""
val1 = gen_uid(8)
val2 = gen_uid(8, uid_format=True)
self.assertEqual(len(val1), 16)
self.assertTrue(val2.startswith("BlinkCamera_"))
val2_cut = val2.split("_")
val2_split = val2_cut[1].split("-")
self.assertEqual(len(val2_split[0]), 8)
self.assertEqual(len(val2_split[1]), 4)
self.assertEqual(len(val2_split[2]), 4)
self.assertEqual(len(val2_split[3]), 4)
self.assertEqual(len(val2_split[4]), 12)
+2 -3
View File
@@ -1,5 +1,5 @@
[tox]
envlist = build, py36, py37, py38, lint
envlist = build, py36, py37, py38, py39, lint
skip_missing_interpreters = True
skipsdist = True
@@ -41,8 +41,7 @@ commands =
flake8 blinkpy tests app
pydocstyle blinkpy tests app
black --check --diff blinkpy tests app
rst-lint README.rst
rst-lint CHANGES.rst
rst-lint README.rst CHANGES.rst CONTRIBUTING.rst
[testenv:build]
recreate = True