Skip to content

Commit d1463b1

Browse files
authored
Merge pull request #1205 from kaburagisec/dev
ONVIF Profile S, Actions API, and PTZ Controls Implementation
2 parents d45ec65 + 43e5426 commit d1463b1

149 files changed

Lines changed: 21262 additions & 1426 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/docs/developers/documentation.mdx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ const ComponentMetadata: Component = {
5555
title: "Fancy Component",
5656
name: "fancy_component",
5757
description: "A fancy component",
58-
image: "/img/components/fancy_component.png",
58+
image: "/img/components/fancy_component.svg", // SVG assets are prioritized.
5959
tags: ["motion_detector"],
60+
category: "new", // Set to null if it has already been published in a previous version.
61+
path: "viseron/components/fancy_component",
62+
issue: "fancy_component",
6063
};
6164
6265
export default ComponentMetadata;
@@ -69,13 +72,16 @@ If domains are set up in the component, they will be automatically added to the
6972
The following tags are available:
7073

7174
- `camera`
72-
- `face_recognition`
73-
- `image_classification`
74-
- `license_plate_recognition`
75-
- `motion_detector`
7675
- `nvr`
77-
- `object_detector`
7876
- `system`
77+
- `protocol`
78+
- `notification`
79+
- `object_detector`
80+
- `motion_detector`
81+
- `image_classification`
82+
- `face_recognition`
83+
- `license_plate_recognition`
84+
- `integration`
7985

8086
:::warning
8187

docs/docs/documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Viserons features include, but not limited to the following:
2020
- Tiered storage, allowing multiple storage media with different retention policies
2121
- A timeline view of events
2222
- Built in authentication system
23+
- [ONVIF](https://www.onvif.org/) compatible with Profile S
2324
- Object detection via:
2425
- YOLOv3, YOLOv4 and YOLOv7 Darknet using OpenCV
2526
- Tensorflow via [Google Coral EdgeTPU](https://coral.ai/)

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"scripts": {
66
"docusaurus": "docusaurus",
7+
"prebuild": "node src/lib/generateCommitDates.mjs",
78
"start": "docusaurus start --host=0.0.0.0",
89
"build": "docusaurus build",
910
"swizzle": "docusaurus swizzle",
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{
2+
"viseron/components/background_subtractor": {
3+
"created": "2021-11-23T11:41:33Z",
4+
"updated": "2026-03-06T18:38:28Z"
5+
},
6+
"viseron/components/codeprojectai": {
7+
"created": "2023-04-27T12:09:31Z",
8+
"updated": "2026-02-04T09:03:49Z"
9+
},
10+
"viseron/components/compreface": {
11+
"created": "2022-11-01T16:12:07Z",
12+
"updated": "2026-04-16T20:46:29Z"
13+
},
14+
"viseron/components/darknet": {
15+
"created": "2021-12-06T15:10:41Z",
16+
"updated": "2026-04-16T20:57:53Z"
17+
},
18+
"viseron/components/deepstack": {
19+
"created": "2021-12-07T06:25:47Z",
20+
"updated": "2026-02-04T09:03:49Z"
21+
},
22+
"viseron/components/discord": {
23+
"created": "2025-03-17T23:00:48Z",
24+
"updated": "2026-06-24T15:09:38Z"
25+
},
26+
"viseron/components/dlib": {
27+
"created": "2021-12-27T14:26:06Z",
28+
"updated": "2026-04-17T20:29:01Z"
29+
},
30+
"viseron/components/edgetpu": {
31+
"created": "2021-11-01T10:25:23Z",
32+
"updated": "2026-04-17T20:35:02Z"
33+
},
34+
"viseron/components/ffmpeg": {
35+
"created": "2021-10-19T20:22:12Z",
36+
"updated": "2026-05-15T14:57:37Z"
37+
},
38+
"viseron/components/go2rtc": {
39+
"created": "2025-04-29T09:09:42Z",
40+
"updated": "2026-07-30T20:54:04Z"
41+
},
42+
"viseron/components/gotify": {
43+
"created": "2025-03-18T01:55:20Z",
44+
"updated": "2026-03-13T22:17:22Z"
45+
},
46+
"viseron/components/gstreamer": {
47+
"created": "2022-03-02T17:36:39Z",
48+
"updated": "2026-05-02T12:41:46Z"
49+
},
50+
"viseron/components/hailo": {
51+
"created": "2025-09-10T05:21:41Z",
52+
"updated": "2026-04-17T20:31:34Z"
53+
},
54+
"viseron/components/logger": {
55+
"created": "2021-10-11T12:53:55Z",
56+
"updated": "2026-03-26T14:02:48Z"
57+
},
58+
"viseron/components/mog2": {
59+
"created": "2021-11-23T11:40:40Z",
60+
"updated": "2026-03-14T21:48:33Z"
61+
},
62+
"viseron/components/mqtt": {
63+
"created": "2021-12-22T12:52:23Z",
64+
"updated": "2026-06-08T15:13:58Z"
65+
},
66+
"viseron/components/nvr": {
67+
"created": "2021-10-25T12:29:15Z",
68+
"updated": "2026-06-08T15:13:58Z"
69+
},
70+
"viseron/components/onvif": null,
71+
"viseron/components/storage": {
72+
"created": "2023-06-12T15:05:18Z",
73+
"updated": "2026-07-29T21:33:00Z"
74+
},
75+
"viseron/components/telegram": {
76+
"created": "2024-07-29T21:40:23Z",
77+
"updated": "2026-06-22T09:44:12Z"
78+
},
79+
"viseron/components/webhook": {
80+
"created": "2025-08-15T12:18:50Z",
81+
"updated": "2026-06-17T10:15:15Z"
82+
},
83+
"viseron/components/webserver": {
84+
"created": "2021-10-12T14:58:37Z",
85+
"updated": "2026-07-08T21:16:12Z"
86+
},
87+
"viseron/components/yolo": {
88+
"created": "2025-06-22T17:09:46Z",
89+
"updated": "2026-06-16T16:43:39Z"
90+
}
91+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import fs from "fs";
2+
import path from "path";
3+
4+
const ROOT =
5+
"src/pages/components-explorer/components";
6+
7+
const OUTPUT =
8+
"src/generated/commitDates.json";
9+
10+
const BASE_URL =
11+
"https://api.github.com/repos/roflcoopter/viseron/commits";
12+
13+
const headers = {
14+
/**
15+
...(process.env.GITHUB_TOKEN
16+
? { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` }
17+
: {}),
18+
*/
19+
Accept: "application/vnd.github+json",
20+
};
21+
22+
/**
23+
* Recursively find all _meta.tsx files
24+
*/
25+
function findMetaFiles(dir) {
26+
const entries = fs.readdirSync(dir, { withFileTypes: true });
27+
const result = [];
28+
29+
for (const e of entries) {
30+
const full = path.join(dir, e.name);
31+
if (e.isDirectory()) {
32+
result.push(...findMetaFiles(full));
33+
} else if (e.name === "_meta.tsx") {
34+
result.push(full);
35+
}
36+
}
37+
return result;
38+
}
39+
40+
/**
41+
* Extract `path: "..."` from _meta.tsx source
42+
*/
43+
function extractPathFromMeta(filePath) {
44+
const content = fs.readFileSync(filePath, "utf8");
45+
46+
const match = content.match(
47+
/path\s*:\s*["'`]([^"'`]+)["'`]/
48+
);
49+
50+
return match?.[1] ?? null;
51+
}
52+
53+
async function fetchCommitDates(repoPath) {
54+
const encoded = encodeURIComponent(repoPath);
55+
56+
// latest commit
57+
const latestRes = await fetch(
58+
`${BASE_URL}?sha=master&path=${encoded}&per_page=1`,
59+
{ headers }
60+
);
61+
const latest = await latestRes.json();
62+
if (!Array.isArray(latest) || latest.length === 0) {
63+
return null;
64+
}
65+
66+
const updated = latest[0].commit.author.date;
67+
68+
// oldest commit (paginate)
69+
let page = 1;
70+
let created = updated;
71+
72+
while (true) {
73+
const res = await fetch(
74+
`${BASE_URL}?sha=master&path=${encoded}&per_page=100&page=${page}`,
75+
{ headers }
76+
);
77+
const data = await res.json();
78+
if (!Array.isArray(data) || data.length === 0) break;
79+
80+
created =
81+
data[data.length - 1].commit.author.date;
82+
83+
if (data.length < 100) break;
84+
page++;
85+
}
86+
87+
return { created, updated };
88+
}
89+
90+
async function main() {
91+
const metaFiles = findMetaFiles(ROOT);
92+
const result = {};
93+
94+
for (const file of metaFiles) {
95+
const repoPath = extractPathFromMeta(file);
96+
if (!repoPath) continue;
97+
98+
result[repoPath] = await fetchCommitDates(repoPath);
99+
}
100+
101+
fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
102+
fs.writeFileSync(OUTPUT, JSON.stringify(result, null, 2));
103+
}
104+
105+
main().catch(console.error);

docs/src/lib/getCommitsDates.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import data from "@site/src/generated/commitDates.json";
2+
3+
type CommitDates = {
4+
created?: string;
5+
updated?: string;
6+
};
7+
8+
export default function useCommitDates(path: string): CommitDates {
9+
return data[path] ?? {};
10+
}

docs/src/lib/iconMap.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {
44
Chip,
55
ConnectionSignal,
66
FaceActivated,
7-
GroupObjects,
8-
ImageReference,
7+
WatsonHealth3DMprToggle,
8+
VisualRecognition,
99
Movement,
1010
Notification,
1111
Video,
@@ -18,8 +18,8 @@ export const iconMap: Record<string, CarbonIconType> = {
1818
CarFront,
1919
ConnectionSignal,
2020
FaceActivated,
21-
GroupObjects,
22-
ImageReference,
21+
WatsonHealth3DMprToggle,
22+
VisualRecognition,
2323
Movement,
2424
Notification,
2525
Chip,

docs/src/pages/components-explorer/_components/ComponentHeader/index.tsx

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React from "react";
2-
2+
import { Debug, LogoGithub } from "@carbon/icons-react";
33
import Head from "@docusaurus/Head";
4+
import Link from "@docusaurus/Link";
45
import Heading from "@theme/Heading";
56

7+
import useCommitDates from "@site/src/lib/getCommitsDates";
68
import { getIconComponent } from "@site/src/lib/iconMap";
79
import { Component, DomainType, Domains } from "@site/src/types";
810

@@ -37,6 +39,8 @@ function TagBadge({ tag }: { tag: DomainType }) {
3739
}
3840

3941
function ComponentHeader({ meta }: { meta: Component }) {
42+
const { created, updated } = useCommitDates(meta.path);
43+
4044
return (
4145
<div>
4246
<Head>
@@ -68,7 +72,66 @@ function ComponentHeader({ meta }: { meta: Component }) {
6872
</div>
6973
<img src={meta.image} alt={meta.title} />
7074
</div>
71-
<hr className="divider" />
75+
<hr className="divider" style={{ marginBottom: 10 }} />
76+
<div
77+
style={{
78+
display: "flex",
79+
justifyContent: "space-between",
80+
alignItems: "center",
81+
}}
82+
>
83+
<div
84+
style={{
85+
display: "flex",
86+
alignItems: "center",
87+
columnGap: 20,
88+
}}
89+
>
90+
<div
91+
style={{
92+
color: "gray",
93+
}}
94+
>
95+
Created: {created ? new Date(created).toLocaleDateString() : "—"}
96+
</div>
97+
<div
98+
style={{
99+
color: "gray",
100+
}}
101+
>
102+
Updated: {updated ? new Date(updated).toLocaleDateString() : "—"}
103+
</div>
104+
</div>
105+
<div
106+
style={{
107+
display: "flex",
108+
alignItems: "center",
109+
columnGap: 20,
110+
}}
111+
>
112+
<Link
113+
href={`https://github.com/roflcoopter/viseron/tree/master/${meta.path}`}
114+
style={{
115+
display: "flex",
116+
alignItems: "center",
117+
}}
118+
>
119+
<LogoGithub />
120+
&nbsp;View source on Github
121+
</Link>
122+
<Link
123+
href={`https://github.com/roflcoopter/viseron/issues?q=is:issue%20${meta.issue}`}
124+
style={{
125+
display: "flex",
126+
alignItems: "center",
127+
}}
128+
>
129+
<Debug />
130+
&nbsp;View all issues
131+
</Link>
132+
</div>
133+
</div>
134+
<hr className="divider" style={{ marginTop: 10 }} />
72135
</div>
73136
);
74137
}

docs/src/pages/components-explorer/_components/ComponentHeader/styles.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
}
77

88
.header img {
9-
max-height: 67px;
10-
max-width: 100%;
9+
max-height: 90px;
10+
max-width: 200px;
1111
}
1212

1313
@media only screen and (max-width: 600px) {

docs/src/pages/components-explorer/components/background_subtractor/_meta.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const ComponentMetadata: Component = {
88
image: "/img/logos/opencv.svg",
99
tags: ["motion_detector"],
1010
category: null,
11+
path: "viseron/components/background_subtractor",
12+
issue: 'background_subtractor OR label:"component: background_subtractor" OR label:"domain: motion_detector"',
1113
};
1214

1315
export default ComponentMetadata;

0 commit comments

Comments
 (0)