Skip to content

Commit

Permalink
Feature/camera card (#84)
Browse files Browse the repository at this point in the history
* useCamera hook to retrieve custom information for the camera

* preparing for release

* last cleanups
  • Loading branch information
shannonhochkins authored Oct 26, 2023
1 parent 80c6e17 commit dac8262
Show file tree
Hide file tree
Showing 51 changed files with 2,731 additions and 671 deletions.
12 changes: 12 additions & 0 deletions .d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
declare module '*.svg' {
const value: any;
export = value;
}
declare module '*.jpg' {
const value: any;
export = value;
}
declare module '*.npg' {
const value: any;
export = value;
}
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# 2.3.0
## @hakit/components
- NEW - CameraCard - a component to render / preview a camera entity in home assistant, it supports live, motion and rolling poster views, this is a very complicated component and I'd love feedback if you have issues or even if it works for you!
- NEW - AreaCard & PictureCard now preload the image with a loader, the preloaderProps are also configurable from these cards
- BUGFIX - AreaCard wasn't stretching when inside a Row or Column in stretch mode, this has been fixed
- NEW - FabCard - now changes border radius automatically when providing children to use as a normal button, this may trigger the component to be renamed to something more suitable later on
- BUGFIX - SensorCard - wasn't allowing manual historyOptions to update
- BREAKING - SidebarCard & TimeCard - includeIcon and includeDate have been renamed to hideIcon and hideDate to align with other component prop names - if you're using these properties you'll have to invert your logic
- NEW - TimeCard - you can now hide individual elements on the card making it completely custom
- NEW - GroupCard - you can now add an optional description to the group which will appear under the title
- BUGFIX - ButtonGroup - wasn't stretching when inside a row/column with stretch
- NEW - Row/Column now also adds the classes of the flex layout properties to the element for styling purposes
- NEW - PreloadImage - a shared component allowing you to preload any image, this is used by AreaCard and PictureCard

## @hakit/core
- BREAKING - useEntity - previously was subsribing to history updates for every entity, this has been disabled for performance reasons, this now needs to be opted into subscription:
```
const lightStrip = useEntity('light.office_striplight', {
returnNullIfNotFound: true,
history: {
disable: false,
hoursToShow: 96 // defaults to 24
}
});
```
- NEW - useCamera - a hook to return all the complex logic of fetching / retrieving poster, stream and mjpeg urls in a very simple hook.
- NEW - joinHassUrl - a function exposed from useHass() that allows you to provide a pathname to an asset on your home assistant instance, and join it with your home assistant url. If your entity has a local path to an image, you can use this to request it from your instance.
- BUGFIX - There's a bug with the route addition causing the page to completely freeze recursively due to the nature of hash updates and react updates not syncing correctly, this has been fixed
- BUGFIX - callApi second argument options is now optional and will perform a GET request by default
- BUGFIX - useAreas now returns a fully qualified picture url to your home assistant instance, this was previously returning a local path
- NEW - there's a few other functions exposed from core to help with camera entites:
- fetchCameraPrefs
- isCameraMediaSource
- getEntityIdFromCameraMediaSource
- computeMJPEGStreamUrl
- fetchThumbnailUrlWithCache
- fetchStreamUrl

# 2.2.0
## @hakit/components
- BREAKING - renamed RoomCard to AreaCard to align with naming convention of home assistant seeing as they use "areas" rather than "rooms". RoomCard is still available but marked as deprecated, this will be removed in future releases.
Expand Down
Binary file added hass-connect-fake/assets/reolink-snapshot.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion hass-connect-fake/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
HassConfig,
Auth,
HaWebSocket,
MessageBase,
} from "home-assistant-js-websocket";
import { Connection } from "home-assistant-js-websocket";
import type {
Expand All @@ -26,7 +27,8 @@ import fakeApi from './mocks/fake-call-service';
import { create } from 'zustand';
import type { ServiceArgs } from './mocks/fake-call-service/types';
import mockHistory from './mock-history';
import { mockCallApi } from './mocks/fake-call-api'
import { mockCallApi } from './mocks/fake-call-api';
import reolinkSnapshot from './assets/reolink-snapshot.jpg';

interface CallServiceArgs<T extends SnakeOrCamelDomains, M extends DomainService<T>> {
domain: T;
Expand Down Expand Up @@ -140,6 +142,15 @@ class MockConnection extends Connection {
callback(mockHistory as Result);
return () => Promise.resolve();
}
async sendMessagePromise<Result>(message: MessageBase): Promise<Result> {
// a mock for the proxy image for the camera
if (message.path && message.path.includes('camera_proxy')) {
return {
path: `${reolinkSnapshot}?`
} as Result;
}
return null as Result;
}
}

const useStore = create<Store>((set) => ({
Expand Down Expand Up @@ -327,6 +338,7 @@ function HassProvider({
[_hash, routes, setRoutes],
);

const joinHassUrl = useCallback((path: string) => path, []);

const getRoute = useCallback(
(hash: string) => {
Expand Down Expand Up @@ -356,6 +368,7 @@ function HassProvider({
getAllEntities,
callService,
callApi,
joinHassUrl,
}}
>
{children(ready)}
Expand Down
24 changes: 24 additions & 0 deletions hass-connect-fake/mocks/createBinarySensor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { HassEntity } from 'home-assistant-js-websocket';
import { createEntity } from './createEntity';

const now = new Date();

const defaults = {
entity_id: "binary_sensor.vehicle",
state: "off",
attributes: {
icon: "mdi:car-off",
friendly_name: "Time",
},
context: {
id: "01H4JAXGF1RTA2MJGGPGAGM7VD",
parent_id: null,
user_id: null,
},
last_changed: now.toISOString(),
last_updated: now.toISOString(),
} satisfies HassEntity;

export const createBinarySensor = (entity_id: string, overrides: Partial<HassEntity> = {}) => {
return createEntity(entity_id, defaults, overrides);
}
29 changes: 29 additions & 0 deletions hass-connect-fake/mocks/createCamera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@


import { HassEntity } from 'home-assistant-js-websocket';
import { createEntity } from './createEntity';

const now = new Date();

const defaults = {
entity_id: "camera.demo_camera",
state: "idle",
attributes: {
access_token: "FAKE_TOKEN",
frontend_stream_type: "hls",
entity_picture: "FAKE_PICTURE",
friendly_name: "Frontdoor Camera",
supported_features: 2
},
context: {
id: "01HG7Q3VK1E31HD36JZ2ZCXA32",
parent_id: null,
user_id: null
},
last_changed: now.toISOString(),
last_updated: now.toISOString()
} satisfies HassEntity;

export const createCamera = (entity_id: string, overrides: Partial<HassEntity> = {}) => {
return createEntity(entity_id, defaults, overrides);
}
11 changes: 11 additions & 0 deletions hass-connect-fake/mocks/mockEntities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,25 @@ import { createClimate } from './createClimate';
import { createVacuum } from './createVacuum';
import { createAutomation } from './createAutomation';
import { createCalendar } from './createCalendar';
import { createCamera } from './createCamera';
import { createBinarySensor } from './createBinarySensor';

export const entities: HassEntities = {
...createCamera('camera.demo_camera'),
...createLight('light.unavailable', {
"state": "unavailable",
attributes: {
friendly_name: 'Unavailable light demo',
}
}),
...createSwitch('switch.record', {
attributes: {
icon: "mdi:record-rec",
friendly_name: "Backyard Record"
},
state: 'on'
}),
...createBinarySensor('binary_sensor.vehicle'),
...createLight("light.fake_light_1", {
attributes: {
friendly_name: "Dining room light",
Expand Down
31 changes: 22 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"@fullcalendar/react": "^6.1.9",
"@hakit/core": "^2.2.0",
"@use-gesture/react": ">=10.x",
"autolinker": ">=4.x",
"framer-motion": ">=10.x",
"fullcalendar": "^6.1.9",
"lodash": ">=4.x",
Expand All @@ -80,7 +81,7 @@
"react-router-dom": ">=6.x",
"react-thermostat": "^2.x.x",
"react-use": ">=17.x",
"autolinker": ">=4.x"
"hls.js": "^1.4.12"
},
"devDependencies": {
"@emotion/babel-plugin": "^11.x",
Expand Down
Loading

0 comments on commit dac8262

Please sign in to comment.