camstreamerlib 1.8.7 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CamScripterAPICameraEventsGenerator.d.ts +59 -0
- package/CamScripterAPICameraEventsGenerator.js +148 -0
- package/CreatePackage.js +8 -3
- package/README.md +25 -319
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import * as EventEmitter from 'events';
|
|
3
|
+
export declare type CamScripterOptions = {
|
|
4
|
+
tls?: boolean;
|
|
5
|
+
tlsInsecure?: boolean;
|
|
6
|
+
ip?: string;
|
|
7
|
+
port?: number;
|
|
8
|
+
auth?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare type Declaration = {
|
|
11
|
+
type?: '' | 'SOURCE' | 'DATA';
|
|
12
|
+
namespace: string;
|
|
13
|
+
key: string;
|
|
14
|
+
value: string | boolean | number;
|
|
15
|
+
value_type: 'STRING' | 'INT' | 'BOOL' | 'DOUBLE';
|
|
16
|
+
key_nice_name?: string;
|
|
17
|
+
value_nice_name?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare type EventDeclaration = {
|
|
20
|
+
declaration_id: string;
|
|
21
|
+
stateless: boolean;
|
|
22
|
+
declaration: Declaration[];
|
|
23
|
+
};
|
|
24
|
+
export declare type EventUndeclaration = {
|
|
25
|
+
declaration_id: string;
|
|
26
|
+
};
|
|
27
|
+
export declare type EventData = {
|
|
28
|
+
namespace: string;
|
|
29
|
+
key: string;
|
|
30
|
+
value: string | boolean | number;
|
|
31
|
+
value_type: 'STRING' | 'INT' | 'BOOL' | 'DOUBLE';
|
|
32
|
+
};
|
|
33
|
+
export declare type Event = {
|
|
34
|
+
declaration_id: string;
|
|
35
|
+
event_data: EventData[];
|
|
36
|
+
};
|
|
37
|
+
export declare type Response = {
|
|
38
|
+
call_id: number;
|
|
39
|
+
message: string;
|
|
40
|
+
};
|
|
41
|
+
export declare class CamScripterAPICameraEventsGenerator extends EventEmitter {
|
|
42
|
+
private tls;
|
|
43
|
+
private tlsInsecure;
|
|
44
|
+
private ip;
|
|
45
|
+
private port;
|
|
46
|
+
private auth;
|
|
47
|
+
private callId;
|
|
48
|
+
private sendMessages;
|
|
49
|
+
private ws;
|
|
50
|
+
constructor(options?: CamScripterOptions);
|
|
51
|
+
connect(): Promise<void>;
|
|
52
|
+
private openWebsocket;
|
|
53
|
+
declareEvent(eventDeclaration: EventDeclaration): Promise<Response>;
|
|
54
|
+
undeclareEvent(eventUndeclaration: EventUndeclaration): Promise<Response>;
|
|
55
|
+
sendEvent(event: Event): Promise<Response>;
|
|
56
|
+
private sendMessage;
|
|
57
|
+
private reportErr;
|
|
58
|
+
private reportClose;
|
|
59
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CamScripterAPICameraEventsGenerator = void 0;
|
|
13
|
+
const WebSocket = require("ws");
|
|
14
|
+
const EventEmitter = require("events");
|
|
15
|
+
const Digest_1 = require("./Digest");
|
|
16
|
+
class CamScripterAPICameraEventsGenerator extends EventEmitter {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
var _a, _b, _c, _d, _e;
|
|
19
|
+
super();
|
|
20
|
+
this.ws = null;
|
|
21
|
+
this.tls = (_a = options === null || options === void 0 ? void 0 : options.tls) !== null && _a !== void 0 ? _a : false;
|
|
22
|
+
this.tlsInsecure = (_b = options === null || options === void 0 ? void 0 : options.tlsInsecure) !== null && _b !== void 0 ? _b : false;
|
|
23
|
+
this.ip = (_c = options === null || options === void 0 ? void 0 : options.ip) !== null && _c !== void 0 ? _c : '127.0.0.1';
|
|
24
|
+
this.port = (_d = options === null || options === void 0 ? void 0 : options.port) !== null && _d !== void 0 ? _d : (this.tls ? 443 : 80);
|
|
25
|
+
this.auth = (_e = options === null || options === void 0 ? void 0 : options.auth) !== null && _e !== void 0 ? _e : '';
|
|
26
|
+
this.callId = 0;
|
|
27
|
+
this.sendMessages = {};
|
|
28
|
+
EventEmitter.call(this);
|
|
29
|
+
}
|
|
30
|
+
connect() {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
try {
|
|
33
|
+
yield this.openWebsocket();
|
|
34
|
+
this.emit('open');
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
this.reportErr(err);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
openWebsocket(digestHeader) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const userPass = this.auth.split(':');
|
|
44
|
+
const protocol = this.tls ? 'wss' : 'ws';
|
|
45
|
+
const addr = `${protocol}://${this.ip}:${this.port}/local/camscripter/ws`;
|
|
46
|
+
const options = {
|
|
47
|
+
auth: this.auth,
|
|
48
|
+
rejectUnauthorized: !this.tlsInsecure,
|
|
49
|
+
headers: {},
|
|
50
|
+
};
|
|
51
|
+
if (digestHeader !== undefined) {
|
|
52
|
+
options.headers['Authorization'] = Digest_1.Digest.getAuthHeader(userPass[0], userPass[1], 'GET', '/local/camscripter/ws', digestHeader);
|
|
53
|
+
}
|
|
54
|
+
this.ws = new WebSocket(addr, 'camera-events', options);
|
|
55
|
+
this.ws.binaryType = 'arraybuffer';
|
|
56
|
+
this.ws.isAlive = true;
|
|
57
|
+
const pingTimer = setInterval(() => {
|
|
58
|
+
if (this.ws.readyState !== this.ws.OPEN || this.ws.isAlive === false) {
|
|
59
|
+
return this.ws.terminate();
|
|
60
|
+
}
|
|
61
|
+
this.ws.isAlive = false;
|
|
62
|
+
this.ws.ping();
|
|
63
|
+
}, 30000);
|
|
64
|
+
this.ws.on('open', () => {
|
|
65
|
+
resolve();
|
|
66
|
+
});
|
|
67
|
+
this.ws.on('pong', () => {
|
|
68
|
+
this.ws.isAlive = true;
|
|
69
|
+
});
|
|
70
|
+
this.ws.on('message', (data) => {
|
|
71
|
+
const dataJSON = JSON.parse(data);
|
|
72
|
+
if (dataJSON.hasOwnProperty('call_id') && dataJSON['call_id'] in this.sendMessages) {
|
|
73
|
+
if (dataJSON.hasOwnProperty('error')) {
|
|
74
|
+
this.sendMessages[dataJSON['call_id']].reject(new Error(dataJSON.error));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this.sendMessages[dataJSON['call_id']].resolve(dataJSON);
|
|
78
|
+
}
|
|
79
|
+
delete this.sendMessages[dataJSON['call_id']];
|
|
80
|
+
}
|
|
81
|
+
if (dataJSON.hasOwnProperty('error')) {
|
|
82
|
+
this.reportErr(new Error(dataJSON.error));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
this.ws.on('unexpected-response', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
if (res.statusCode === 401 && res.headers['www-authenticate'] !== undefined)
|
|
87
|
+
this.openWebsocket(res.headers['www-authenticate']).then(resolve, reject);
|
|
88
|
+
else {
|
|
89
|
+
reject('Error: status code: ' + res.statusCode + ', ' + res.data);
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
this.ws.on('error', (error) => {
|
|
93
|
+
this.reportErr(error);
|
|
94
|
+
reject(error);
|
|
95
|
+
});
|
|
96
|
+
this.ws.on('close', () => {
|
|
97
|
+
clearInterval(pingTimer);
|
|
98
|
+
this.reportClose();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
declareEvent(eventDeclaration) {
|
|
103
|
+
return this.sendMessage({
|
|
104
|
+
call_id: 0,
|
|
105
|
+
command: 'declare_event',
|
|
106
|
+
data: eventDeclaration,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
undeclareEvent(eventUndeclaration) {
|
|
110
|
+
return this.sendMessage({
|
|
111
|
+
call_id: 0,
|
|
112
|
+
command: 'undeclare_event',
|
|
113
|
+
data: eventUndeclaration,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
sendEvent(event) {
|
|
117
|
+
return this.sendMessage({
|
|
118
|
+
call_id: 0,
|
|
119
|
+
command: 'send_event',
|
|
120
|
+
data: event,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
sendMessage(msgJson) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
try {
|
|
126
|
+
this.sendMessages[this.callId] = { resolve, reject };
|
|
127
|
+
msgJson.call_id = this.callId++;
|
|
128
|
+
this.ws.send(JSON.stringify(msgJson));
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
this.reportErr(new Error(`Send message error: ${err}`));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
reportErr(err) {
|
|
136
|
+
var _a;
|
|
137
|
+
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
138
|
+
this.emit('error', err);
|
|
139
|
+
}
|
|
140
|
+
reportClose() {
|
|
141
|
+
for (const callId in this.sendMessages) {
|
|
142
|
+
this.sendMessages[callId].reject(new Error('Connection lost'));
|
|
143
|
+
}
|
|
144
|
+
this.sendMessages = {};
|
|
145
|
+
this.emit('close');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.CamScripterAPICameraEventsGenerator = CamScripterAPICameraEventsGenerator;
|
package/CreatePackage.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const Path = require("path");
|
|
5
3
|
const AdmZip = require("adm-zip");
|
|
4
|
+
const Path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
6
|
function isDirectory(path) {
|
|
7
7
|
const stat = fs.statSync(path);
|
|
8
8
|
return stat.isDirectory();
|
|
@@ -26,7 +26,8 @@ function createZipArchive(zip, folder, options) {
|
|
|
26
26
|
if (file[0] === '.' ||
|
|
27
27
|
zipFileRegex.test(file) ||
|
|
28
28
|
(file === 'node_modules' && !options.includeNodeModules) ||
|
|
29
|
-
(file === 'src' && options.typeScriptPackage)
|
|
29
|
+
(file === 'src' && options.typeScriptPackage) ||
|
|
30
|
+
options.excludedFileNames.includes(file)) {
|
|
30
31
|
continue;
|
|
31
32
|
}
|
|
32
33
|
else if (file === 'dist' && options.typeScriptPackage) {
|
|
@@ -44,11 +45,15 @@ function main(args) {
|
|
|
44
45
|
const options = {
|
|
45
46
|
includeNodeModules: false,
|
|
46
47
|
typeScriptPackage: false,
|
|
48
|
+
excludedFileNames: [],
|
|
47
49
|
};
|
|
48
50
|
for (let arg of args) {
|
|
49
51
|
if (arg === '-i' || arg === '-includeNodeModules') {
|
|
50
52
|
options.includeNodeModules = true;
|
|
51
53
|
}
|
|
54
|
+
if (arg.startsWith('-e=') || arg.startsWith('-exclude=')) {
|
|
55
|
+
options.excludedFileNames = arg.substring(arg.indexOf('=') + 1).split(',');
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
if (fs.existsSync('dist')) {
|
|
54
59
|
options.typeScriptPackage = true;
|
package/README.md
CHANGED
|
@@ -1,350 +1,56 @@
|
|
|
1
1
|
# CamStreamerLib
|
|
2
|
+
|
|
2
3
|
Node.js helper library for CamStreamer ACAP applications.
|
|
3
4
|
|
|
4
5
|
The library is primarily developed for CamScripter Acap application running directly in Axis cameras.
|
|
5
6
|
Examples of CamScripter packages can be found at https://github.com/CamStreamer/CamScripterApp_examples
|
|
6
7
|
|
|
7
8
|
## Installation
|
|
9
|
+
|
|
8
10
|
```
|
|
9
11
|
npm install camstreamerlib
|
|
10
12
|
```
|
|
11
13
|
|
|
12
14
|
# Documentation for Node.js modules
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
It registers callback for access to specified path. Callback has attributes - request and response.
|
|
20
|
-
|
|
21
|
-
#### close()
|
|
22
|
-
Closes httpServer service and frees up the occupied port.
|
|
23
|
-
|
|
24
|
-
##### example
|
|
25
|
-
```javascript
|
|
26
|
-
httpServer.onRequest('/settings.cgi', function(req, res) {
|
|
27
|
-
res.statusCode = 200;
|
|
28
|
-
res.setHeader('Content-type', 'application/json');
|
|
29
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
30
|
-
res.end('{"enabled": true}');
|
|
31
|
-
});
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### events
|
|
35
|
-
#### access(msg)
|
|
36
|
-
The Event is emitted for all HTTP requests to this server
|
|
37
|
-
#### error(err)
|
|
38
|
-
An error occurs
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## CameraVapix
|
|
42
|
-
Access to Axis camera VAPIX interface. For more details see documentation for Axis camera VAPIX library.
|
|
43
|
-
|
|
44
|
-
### methods
|
|
45
|
-
#### CameraVapix(options)
|
|
46
|
-
```javascript
|
|
47
|
-
options = {
|
|
48
|
-
'protocol': 'http',
|
|
49
|
-
'ip': '127.0.0.1',
|
|
50
|
-
'port': 80,
|
|
51
|
-
'auth': 'root:pass'
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
#### vapixGet(groupNames)
|
|
56
|
-
Universal method for HTTP GET requests to camera VAPIX API.
|
|
57
|
-
##### example
|
|
58
|
-
```javascript
|
|
59
|
-
vapixGet('/axis-cgi/param.cgi?action=list&group=camscripter')
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
#### vapixPost(groupNames)
|
|
63
|
-
Universal method for HTTP POST requests to camera VAPIX API.
|
|
64
|
-
##### example
|
|
65
|
-
```javascript
|
|
66
|
-
vapixPost('/axis-cgi/param.cgi', 'action=update&camscripter.enabled=1')
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
#### getParameterGroup(groupNames)
|
|
70
|
-
Get parameters from the camera.
|
|
71
|
-
##### example
|
|
72
|
-
```javascript
|
|
73
|
-
getParameterGroup('camscripter','camoverlay')
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
#### setParameter(params)
|
|
77
|
-
Set parameters to the camera.
|
|
78
|
-
##### example
|
|
79
|
-
```javascript
|
|
80
|
-
setParameter('{"root.camscripter.Enabled": "1"}')
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
#### getPTZPresetList(channel)
|
|
84
|
-
Get a list of PTZ presets for the specified channel. Channels are numbered from 1.
|
|
85
|
-
##### example
|
|
86
|
-
```javascript
|
|
87
|
-
getPTZPresetList(1)
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
#### goToPreset(channel, presetName)
|
|
91
|
-
Move the camera channel to the PTZ preset.
|
|
92
|
-
##### example
|
|
93
|
-
```javascript
|
|
94
|
-
goToPreset(1, 'home')
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
#### getGuardTourList()
|
|
98
|
-
Get the list of guard tours.
|
|
99
|
-
##### example
|
|
100
|
-
```javascript
|
|
101
|
-
getGuardTourList()
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
#### setGuardTourEnabled(gourTourID, enable)
|
|
105
|
-
Enable or disable the guard tour.
|
|
106
|
-
##### example
|
|
107
|
-
```javascript
|
|
108
|
-
setGuardTourEnabled('root.GuardTour.G0', true)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
#### getInputState(port)
|
|
112
|
-
Get the camera input state for the specified port number.
|
|
113
|
-
##### example
|
|
114
|
-
```javascript
|
|
115
|
-
getInputState(2)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
#### setOutputState(port, active)
|
|
119
|
-
Set the state of the camera output port.
|
|
120
|
-
##### example
|
|
121
|
-
```javascript
|
|
122
|
-
setOutputState(2, true)
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
#### getApplicationList()
|
|
126
|
-
Get the list of installed Acap applications.
|
|
127
|
-
##### example
|
|
128
|
-
```javascript
|
|
129
|
-
getApplicationList()
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### getEventDeclarations()
|
|
133
|
-
Get all the available camera events in JSON format.
|
|
134
|
-
##### example
|
|
135
|
-
```javascript
|
|
136
|
-
getEventDeclarations()
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### events
|
|
140
|
-
#### eventsConnect
|
|
141
|
-
Events connection is ready
|
|
142
|
-
#### eventsDisconnect(err)
|
|
143
|
-
Events connection error
|
|
144
|
-
#### *
|
|
145
|
-
You can listen for events from camera by registrating the appropriate topic
|
|
146
|
-
##### example
|
|
147
|
-
```javascript
|
|
148
|
-
on('axis:CameraApplicationPlatform/VMD/Camera1Profile1/.', function(event) {})
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
## CamStreamerAPI
|
|
153
|
-
Module for easy control of streaming in CamStreamer Acap application.
|
|
154
|
-
|
|
155
|
-
### methods
|
|
156
|
-
#### CameraVapix(options)
|
|
157
|
-
```javascript
|
|
158
|
-
options = {
|
|
159
|
-
'protocol': 'http',
|
|
160
|
-
'ip': '127.0.0.1',
|
|
161
|
-
'port': 80,
|
|
162
|
-
'auth': 'root:pass'
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### getStreamList()
|
|
167
|
-
Get info about CamStreamer streams in JSON format.
|
|
168
|
-
##### example
|
|
169
|
-
```javascript
|
|
170
|
-
getStreamList()
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
#### getStreamParameter(streamID, paramName)
|
|
174
|
-
Get a single parameter of the stream with specified ID.
|
|
175
|
-
##### example
|
|
176
|
-
```javascript
|
|
177
|
-
getStreamParameter('1234', 'enabled')
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### setStreamParameter(streamID, paramName, value)
|
|
181
|
-
Set value of stream parameter.
|
|
182
|
-
##### example
|
|
183
|
-
```javascript
|
|
184
|
-
setStreamParameter('1234', 'enabled', '1')
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### isStreaming(streamID)
|
|
188
|
-
Return the state of streaming.
|
|
189
|
-
##### example
|
|
190
|
-
```javascript
|
|
191
|
-
isStreaming('1234')
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
## CamOverlayAPI
|
|
196
|
-
Module for easy control of CamOverlay drawing API. For more details on supported drawing functions see https://camstreamer.com/camoverlay-api1
|
|
197
|
-
|
|
198
|
-
### methods
|
|
199
|
-
#### CameraVapix(options)
|
|
200
|
-
Options parameter contains access to the camera, service name, service ID and camera. If service ID is not specified, service is automatically created/selected based on serviceName. Specify video channel using parameter camera (in which View Area overlay will be shown). If you need to specify multiple video channels, you can use an array: `camera=[0,1]`. If omitted the default value `camera=0` is used.
|
|
201
|
-
```javascript
|
|
202
|
-
options = {
|
|
203
|
-
'ip': '127.0.0.1',
|
|
204
|
-
'port': 80,
|
|
205
|
-
'auth': 'root:pass',
|
|
206
|
-
'serviceName': 'Drawing Test',
|
|
207
|
-
'serviceID': -1,
|
|
208
|
-
'camera': 0
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
#### connect()
|
|
213
|
-
Connect to CamOverlay WebSocket drawing API.
|
|
214
|
-
##### example
|
|
215
|
-
```javascript
|
|
216
|
-
connect()
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
#### cairo(command, args...)
|
|
220
|
-
Call a function from Cairo library. See https://cairographics.org/manual/
|
|
221
|
-
##### example
|
|
222
|
-
```javascript
|
|
223
|
-
cairo('cairo_image_surface_create', 'CAIRO_FORMAT_ARGB32', 200, 200) // https://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-image-surface-create
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
#### writeText(cairoContext, text, posX, posY, width, height, align, textFitMethod)
|
|
227
|
-
Write aligned text to the box specified by x, y coordinates, width and height. Alignment options: A_RIGHT, A_LEFT, A_CENTER.
|
|
228
|
-
|
|
229
|
-
TextFitMethod options:
|
|
230
|
-
- TFM_SCALE - Text size is adjusted to width and height of the box.
|
|
231
|
-
- TFM_TRUNCATE - Text size truncated to the width of the box.
|
|
232
|
-
- TFM_OVERFLOW - Text overflows the box.
|
|
233
|
-
|
|
234
|
-
##### example
|
|
235
|
-
```javascript
|
|
236
|
-
writeText('cairo0', 'Hello World', 5, 100, 190, 15, 'A_RIGHT', 'TFM_TRUNCATE');
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
#### uploadImageData(imgBuffer)
|
|
240
|
-
Upload .jpg or .png image to the CamOverlay application. Function returns variable name and dimensions of the image.
|
|
241
|
-
##### example
|
|
242
|
-
```javascript
|
|
243
|
-
uploadImageData(fs.readFileSync('image.png'))
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
#### uploadFontData(fontBuffer)
|
|
247
|
-
Upload .ttf font to the CamOverlay application.
|
|
248
|
-
##### example
|
|
249
|
-
```javascript
|
|
250
|
-
uploadFontData(fs.readFileSync('font.ttf'))
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
#### showCairoImage(cairoImage, posX, posY)
|
|
254
|
-
Show image in video stream from the camera. Position is in coordinates -1.0, -1.0 (upper left) / 1.0, 1.0 (bootom right).
|
|
255
|
-
##### example
|
|
256
|
-
```javascript
|
|
257
|
-
showCairoImage('surface0', -1.0, -1.0)
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
#### showCairoImageAbsolute(cairoImage, posX, posY, width, height)
|
|
261
|
-
Show image in video stream from the camera. Position is absolute in pixels, stream resolution is required, because it can be called once there is no video stream running yet.
|
|
262
|
-
##### example
|
|
263
|
-
```javascript
|
|
264
|
-
showCairoImage('surface0', 100, 100, 1920, 1080)
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
#### removeImage()
|
|
268
|
-
Remove image from the camera stream.
|
|
269
|
-
##### example
|
|
270
|
-
```javascript
|
|
271
|
-
removeImage()
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
#### updateCGText(fields)
|
|
275
|
-
Updates text fields listed in parameter fields.
|
|
276
|
-
One field is defined as follows:
|
|
277
|
-
```json
|
|
278
|
-
{
|
|
279
|
-
"field_name": "NAME_OF_YOUR_FIELD",
|
|
280
|
-
"text": "UPDATED_TEXT",
|
|
281
|
-
"color": "COLOR"
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
Parameter "color" is optional.
|
|
285
|
-
|
|
286
|
-
#### updateCGImagePos(coordinates, x, y)
|
|
287
|
-
Changes position of Custom Graphics.
|
|
288
|
-
Coordinates have these values
|
|
289
|
-
```json
|
|
290
|
-
[
|
|
291
|
-
"top_left",
|
|
292
|
-
"top_center",
|
|
293
|
-
"top_right",
|
|
294
|
-
"center_...",
|
|
295
|
-
"...",
|
|
296
|
-
"bottom_...",
|
|
297
|
-
"..."
|
|
298
|
-
]
|
|
299
|
-
```
|
|
16
|
+
- [HttpServer](doc/HttpServer.md) is a module for processing HTTP requests in your scripts. It also automatically serves up the content from html directory or you can register paths which you can process by your own (e.g. http://$CAMERA_IP/local/camscripter/proxy/$MY_PACKAGE_NAME/control.cgi).
|
|
17
|
+
- [CameraVapix](doc/CameraVapix.md) is a module to access Axis camera VAPIX interface.
|
|
18
|
+
- [CamStreamerAPI](doc/CamStreamerAPI.md) is a module for easy control of video streaming in the CamStreamer ACAP application (RTMP, HLS, SRT and MPEG-TS protocols).
|
|
19
|
+
- [CamOverlayAPI](doc/CamOverlayAPI.md) is a module for easy control of CamOverlay drawing API. For more details on supported video overlay drawing functions see https://camstreamer.com/camoverlay-api1
|
|
20
|
+
- [CamScripterAPICameraEventsGenerator](doc/CamScripterAPICameraEventsGenerator.md) is a module which allows generating events on an Axis camera. These events can be used for triggers in the Axis camera rule engine (events/actions). It is also an easy way how to integrate events and metadata in VMS systems which support Axis camera events.
|
|
300
21
|
|
|
301
|
-
|
|
302
|
-
Updates Custom Graphics background to an image with specified path on the camera.
|
|
303
|
-
If no coordinates are specified, the service will use positioning from the last update.
|
|
22
|
+
## For Developers
|
|
304
23
|
|
|
305
|
-
|
|
306
|
-
Updates text in Infoticker service, if any is running.
|
|
24
|
+
### Publishing to npm repository
|
|
307
25
|
|
|
308
|
-
|
|
309
|
-
|
|
26
|
+
1. Update version in package.json and push it
|
|
27
|
+
2. Create git tag e.g. v1.2.4
|
|
310
28
|
|
|
311
|
-
|
|
312
|
-
|
|
29
|
+
- `git tag v1.2.4`
|
|
30
|
+
- `git push --tags`
|
|
313
31
|
|
|
314
|
-
|
|
315
|
-
#### msg(msg)
|
|
316
|
-
WebSocket message received
|
|
317
|
-
#### error(err)
|
|
318
|
-
An error occurs
|
|
319
|
-
#### close
|
|
320
|
-
WebSocket closed
|
|
32
|
+
3. Publish new version to npm
|
|
321
33
|
|
|
322
|
-
|
|
323
|
-
### Publishing with npm
|
|
324
|
-
First log in to the npm service with valid Username, Password and E-mail:
|
|
325
|
-
```bash
|
|
326
|
-
npm login
|
|
327
|
-
```
|
|
328
|
-
The program will prompt you for your information.
|
|
34
|
+
- `npm publish ./dist`
|
|
329
35
|
|
|
330
|
-
|
|
331
|
-
After login, enter your Git repository and run the following command:
|
|
332
|
-
```bash
|
|
333
|
-
np
|
|
334
|
-
```
|
|
335
|
-
The utility will ask you for the prefered version raise and if you are lucky, everything will run just fine.
|
|
336
|
-
Finally, edit GitHub release form.
|
|
36
|
+
4. Edit GitHub release form.
|
|
337
37
|
|
|
338
38
|
### Preparing a package to upload to CamScripter
|
|
39
|
+
|
|
339
40
|
If you want to create your own package and upload it to CamScripter App, you can use the script CreatePackage. It creates a zip file which contains all required files and directories in your package folder. The script accepts source code written either in JavaScript or TypeScript if the package has the correct structure (more information in https://github.com/CamStreamer/CamScripterApp_examples/#readme). To include this script in your package add the following lines in the file package.json:
|
|
41
|
+
|
|
340
42
|
```json
|
|
341
43
|
"scripts": {
|
|
342
44
|
"create-package": "node node_modules/camstreamerlib/CreatePackage.js"
|
|
343
45
|
}
|
|
344
46
|
```
|
|
345
|
-
|
|
47
|
+
|
|
48
|
+
By default, the zipped package does not contain node_modules directory. If you want to include it (required when uploading to CamScripter App on Axis camera), add `-includeNodeModules` or `-i` parameter.
|
|
49
|
+
|
|
50
|
+
If you need to exclude a file or directory add `-exlude` or `-e` parameter with comma separated list.
|
|
51
|
+
|
|
346
52
|
```json
|
|
347
53
|
"scripts": {
|
|
348
|
-
"create-package": "node node_modules/camstreamerlib/CreatePackage.js -
|
|
349
|
-
|
|
54
|
+
"create-package": "node node_modules/camstreamerlib/CreatePackage.js -i -e=react"
|
|
55
|
+
}
|
|
350
56
|
```
|