Version 6.2.0

This commit is contained in:
Chrystian Huot 2022-03-25 12:30:56 -04:00
parent 919ce44059
commit 58a84164ef
26 changed files with 761 additions and 591 deletions

View file

@ -1,5 +1,12 @@
# Change log # Change log
## Version 6.2
- New max clients options which is 200 by default.
- New show listeners count options which is disabled by default (issue #125).
- Fix panic: concurrent write to websocket connection on goroutine.
- Fix units import from SDR Trunk (issue #150).
## Version 6.1 ## Version 6.1
- Calls now support patched talkgroups. - Calls now support patched talkgroups.

View file

@ -26,13 +26,13 @@ Clone the official repository on your computer and start the build process.
When finished, you will find the precompiled versions for various platforms in the `dist` folder. When finished, you will find the precompiled versions for various platforms in the `dist` folder.
rdio-scanner-darwin-amd64-v6.1.16.zip rdio-scanner-darwin-amd64-v6.2.0.zip
rdio-scanner-darwin-arm64-v6.1.16.zip rdio-scanner-darwin-arm64-v6.2.0.zip
rdio-scanner-freebsd-amd64-v6.1.16.zip rdio-scanner-freebsd-amd64-v6.2.0.zip
rdio-scanner-linux-386-v6.1.16.zip rdio-scanner-linux-386-v6.2.0.zip
rdio-scanner-linux-amd64-v6.1.16.zip rdio-scanner-linux-amd64-v6.2.0.zip
rdio-scanner-linux-arm64-v6.1.16.zip rdio-scanner-linux-arm64-v6.2.0.zip
rdio-scanner-linux-arm-v6.1.16.zip rdio-scanner-linux-arm-v6.2.0.zip
rdio-scanner-windows-amd64-v6.1.16.zip rdio-scanner-windows-amd64-v6.2.0.zip
**Happy Rdio scanning !** **Happy Rdio scanning !**

View file

@ -16,8 +16,8 @@
################################################################################ ################################################################################
app := rdio-scanner app := rdio-scanner
date := 2022/03/17 date := 2022/03/25
ver := 6.1.16 ver := 6.2.0
client := $(wildcard client/*.json client/*.ts) client := $(wildcard client/*.json client/*.ts)
server := $(wildcard server/*.go) server := $(wildcard server/*.go)
@ -40,7 +40,7 @@ clean:
container: webapp linux-amd64 container: webapp linux-amd64
@podman login docker.io @podman login docker.io
@podman manifest rm localhost/rdio-scanner:latest || true @podman manifest rm localhost/rdio-scanner:latest || true
@podman build --platform linux/amd64,linux/arm,linux/arm64 --manifest rdio-scanner:latest . @podman build --platform linux/amd64,linux/arm,linux/arm64 --pull --manifest rdio-scanner:latest .
@podman manifest push --format v2s2 localhost/rdio-scanner:latest docker://docker.io/chuot/rdio-scanner:latest @podman manifest push --format v2s2 localhost/rdio-scanner:latest docker://docker.io/chuot/rdio-scanner:latest
dist: darwin freebsd linux windows dist: darwin freebsd linux windows

View file

@ -39,9 +39,11 @@ You can ask your questions or post your comments on the [Rdio Scanner Discussion
# Show your appreciation, support the author # Show your appreciation, support the author
If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated. If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner/stargazers)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated.
If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[consider sponsoring the project](https://github.com/sponsors/chuot)** to help support continued development. If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[sponsor the project](https://github.com/sponsors/chuot)** to help support continued development.
[![Follow us on Twitter](./docs/images/twitter-badge.png?raw=true)](https://twitter.com/RdioScanner)
# Improve your experience on the go # Improve your experience on the go

875
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,28 +1,28 @@
{ {
"author": "Chrystian Huot <chrystian.huot@saubeo.solutions>", "author": "Chrystian Huot <chrystian.huot@saubeo.solutions>",
"dependencies": { "dependencies": {
"@angular/animations": "^13.2.6", "@angular/animations": "^13.3.0",
"@angular/cdk": "^13.2.6", "@angular/cdk": "^13.3.1",
"@angular/common": "~13.2.6", "@angular/common": "~13.3.0",
"@angular/compiler": "~13.2.6", "@angular/compiler": "~13.3.0",
"@angular/core": "~13.2.6", "@angular/core": "~13.3.0",
"@angular/forms": "~13.2.6", "@angular/forms": "~13.3.0",
"@angular/material": "^13.2.6", "@angular/material": "^13.3.1",
"@angular/platform-browser": "~13.2.6", "@angular/platform-browser": "~13.3.0",
"@angular/platform-browser-dynamic": "~13.2.6", "@angular/platform-browser-dynamic": "~13.3.0",
"@angular/router": "^13.2.6", "@angular/router": "^13.3.0",
"@angular/service-worker": "^13.2.6", "@angular/service-worker": "^13.3.0",
"rxjs": "~7.4.0", "rxjs": "~7.4.0",
"tslib": "^2.3.1", "tslib": "^2.3.1",
"zone.js": "~0.11.5" "zone.js": "~0.11.5"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^13.2.6", "@angular-devkit/build-angular": "^13.3.0",
"@angular/cli": "^13.2.6", "@angular/cli": "^13.3.0",
"@angular/compiler-cli": "~13.2.6", "@angular/compiler-cli": "~13.3.0",
"@types/node": "^17.0.21", "@types/node": "^17.0.23",
"@typescript-eslint/eslint-plugin": "^5.15.0", "@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.15.0", "@typescript-eslint/parser": "^5.16.0",
"ajv-keywords": "^5.1.0", "ajv-keywords": "^5.1.0",
"eslint": "^8.11.0", "eslint": "^8.11.0",
"ts-node": "~10.7.0", "ts-node": "~10.7.0",
@ -38,5 +38,5 @@
"build": "ng build --base-href ./ --configuration production", "build": "ng build --base-href ./ --configuration production",
"start": "ng serve" "start": "ng serve"
}, },
"version": "6.1.16" "version": "6.2.0"
} }

View file

@ -135,8 +135,10 @@ export interface Options {
disableDuplicateDetection?: boolean; disableDuplicateDetection?: boolean;
duplicateDetectionTimeFrame?: number; duplicateDetectionTimeFrame?: number;
keypadBeeps?: string; keypadBeeps?: string;
maxClients?: number;
pruneDays?: number; pruneDays?: number;
searchPatchedTalkgroups?: boolean; searchPatchedTalkgroups?: boolean;
showListenersCount?: boolean;
sortTalkgroups?: boolean; sortTalkgroups?: boolean;
tagsToggle?: boolean; tagsToggle?: boolean;
} }
@ -495,8 +497,10 @@ export class RdioScannerAdminService implements OnDestroy {
disableDuplicateDetection: [options?.disableDuplicateDetection], disableDuplicateDetection: [options?.disableDuplicateDetection],
duplicateDetectionTimeFrame: [options?.duplicateDetectionTimeFrame, [Validators.required, Validators.min(0)]], duplicateDetectionTimeFrame: [options?.duplicateDetectionTimeFrame, [Validators.required, Validators.min(0)]],
keypadBeeps: [options?.keypadBeeps, Validators.required], keypadBeeps: [options?.keypadBeeps, Validators.required],
maxClients: [options?.maxClients, [Validators.required, Validators.min(1)]],
pruneDays: [options?.pruneDays, [Validators.required, Validators.min(0)]], pruneDays: [options?.pruneDays, [Validators.required, Validators.min(0)]],
searchPatchedTalkgroups: [options?.searchPatchedTalkgroups], searchPatchedTalkgroups: [options?.searchPatchedTalkgroups],
showListenersCount: [options?.showListenersCount],
sortTalkgroups: [options?.sortTalkgroups], sortTalkgroups: [options?.sortTalkgroups],
tagsToggle: [options?.tagsToggle], tagsToggle: [options?.tagsToggle],
}); });

View file

@ -72,6 +72,21 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="row">
<p>
<span class="mat-body">Max Clients</span><br>
<span class="mat-caption">Max number of simultaneous clients.</span>
</p>
<mat-form-field>
<input type="number" min="0" step="1" matInput formControlName="maxClients">
<mat-error *ngIf="form?.get('maxClients')?.hasError('required')">
Max clients is required
</mat-error>
<mat-error *ngIf="form?.get('maxClients')?.hasError('min')">
Max clients is invalid
</mat-error>
</mat-form-field>
</div>
<div class="row"> <div class="row">
<p> <p>
<span class="mat-body">Prune Days</span><br> <span class="mat-body">Prune Days</span><br>
@ -97,6 +112,15 @@
<mat-slide-toggle color="primary" formControlName="searchPatchedTalkgroups"></mat-slide-toggle> <mat-slide-toggle color="primary" formControlName="searchPatchedTalkgroups"></mat-slide-toggle>
</div> </div>
</div> </div>
<div class="row">
<p>
<span class="mat-body">Show Listeners Count</span><br>
<span class="mat-caption">Show listeners count on main screen.</span>
</p>
<div>
<mat-slide-toggle color="primary" formControlName="showListenersCount"></mat-slide-toggle>
</div>
</div>
<div class="row"> <div class="row">
<p> <p>
<span class="mat-body">Sort Talkgroups</span><br> <span class="mat-body">Sort Talkgroups</span><br>

View file

@ -9,6 +9,9 @@
<div *ngIf="!linked"> <div *ngIf="!linked">
<span>NO LINK</span> <span>NO LINK</span>
</div> </div>
<div *ngIf="linked && showListenersCount">
<span>L: {{ listeners }}</span>
</div>
<div> <div>
<span>Q: {{ callQueue }}</span> <span>Q: {{ callQueue }}</span>
</div> </div>

View file

@ -88,6 +88,8 @@ export class RdioScannerMainComponent implements OnDestroy, OnInit {
linked = false; linked = false;
listeners = 0;
livefeedOffline = true; livefeedOffline = true;
livefeedOnline = false; livefeedOnline = false;
livefeedPaused = false; livefeedPaused = false;
@ -98,6 +100,10 @@ export class RdioScannerMainComponent implements OnDestroy, OnInit {
playbackMode = false; playbackMode = false;
get showListenersCount(): boolean {
return this.config?.showListenersCount || false;
}
@Output() openSearchPanel = new EventEmitter<void>(); @Output() openSearchPanel = new EventEmitter<void>();
@Output() openSelectPanel = new EventEmitter<void>(); @Output() openSelectPanel = new EventEmitter<void>();
@ -381,6 +387,10 @@ export class RdioScannerMainComponent implements OnDestroy, OnInit {
this.linked = event.linked || false; this.linked = event.linked || false;
} }
if ('listeners' in event) {
this.listeners = event.listeners || 0;
}
if ('map' in event) { if ('map' in event) {
this.map = event.map || {}; this.map = event.map || {};
} }

View file

@ -51,6 +51,7 @@ enum WebsocketCommand {
Config = 'CFG', Config = 'CFG',
Expired = 'XPR', Expired = 'XPR',
ListCall = 'LCL', ListCall = 'LCL',
ListenersCount = 'LSC',
LivefeedMap = 'LFM', LivefeedMap = 'LFM',
Max = 'MAX', Max = 'MAX',
Pin = 'PIN', Pin = 'PIN',
@ -79,6 +80,7 @@ export class RdioScannerService implements OnDestroy {
dimmerDelay: false, dimmerDelay: false,
groups: {}, groups: {},
keypadBeeps: false, keypadBeeps: false,
showListenersCount: false,
systems: [], systems: [],
tags: {}, tags: {},
tagsToggle: false, tagsToggle: false,
@ -828,9 +830,10 @@ export class RdioScannerService implements OnDestroy {
dimmerDelay: typeof config.dimmerDelay === 'number' ? config.dimmerDelay : 5000, dimmerDelay: typeof config.dimmerDelay === 'number' ? config.dimmerDelay : 5000,
groups: typeof config.groups !== null && typeof config.groups === 'object' ? config.groups : {}, groups: typeof config.groups !== null && typeof config.groups === 'object' ? config.groups : {},
keypadBeeps: config.keypadBeeps !== null && typeof config.keypadBeeps === 'object' ? config.keypadBeeps : {}, keypadBeeps: config.keypadBeeps !== null && typeof config.keypadBeeps === 'object' ? config.keypadBeeps : {},
showListenersCount: typeof config.showListenersCount === 'boolean' ? config.showListenersCount : false,
systems: Array.isArray(config.systems) ? config.systems.slice() : [], systems: Array.isArray(config.systems) ? config.systems.slice() : [],
tags: typeof config.tags !== null && typeof config.tags === 'object' ? config.tags : {}, tags: typeof config.tags !== null && typeof config.tags === 'object' ? config.tags : {},
tagsToggle: typeof config.tagsToggle !== null && typeof config.tagsToggle === 'boolean' ? config.tagsToggle : false, tagsToggle: typeof config.tagsToggle === 'boolean' ? config.tagsToggle : false,
}; };
this.rebuildLivefeedMap(); this.rebuildLivefeedMap();
@ -871,6 +874,11 @@ export class RdioScannerService implements OnDestroy {
break; break;
case WebsocketCommand.ListenersCount:
this.event.emit({ listeners: message[1] });
break;
case WebsocketCommand.Max: case WebsocketCommand.Max:
this.event.emit({ auth: true, tooMany: true }); this.event.emit({ auth: true, tooMany: true });

View file

@ -92,6 +92,7 @@ export interface RdioScannerConfig {
dimmerDelay: number | false; dimmerDelay: number | false;
groups: { [key: string]: { [key: number]: number[] } }; groups: { [key: string]: { [key: number]: number[] } };
keypadBeeps: RdioScannerKeypadBeeps | false; keypadBeeps: RdioScannerKeypadBeeps | false;
showListenersCount: boolean;
systems: RdioScannerSystem[]; systems: RdioScannerSystem[];
tags: { [key: string]: { [key: number]: number[] } }; tags: { [key: string]: { [key: number]: number[] } };
tagsToggle: boolean; tagsToggle: boolean;
@ -106,6 +107,7 @@ export interface RdioScannerEvent {
holdSys?: boolean; holdSys?: boolean;
holdTg?: boolean; holdTg?: boolean;
linked?: boolean; linked?: boolean;
listeners?: number;
livefeedMode?: RdioScannerLivefeedMode; livefeedMode?: RdioScannerLivefeedMode;
map?: RdioScannerLivefeedMap; map?: RdioScannerLivefeedMap;
pause?: boolean; pause?: boolean;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@macos ~ % mkdir rdio-scanner rdio@macos ~ % mkdir rdio-scanner
rdio@macos ~ % cd rdio-scanner rdio@macos ~ % cd rdio-scanner
rdio@macos rdio-scanner % unzip \ rdio@macos rdio-scanner % unzip \
> ~/Downloads/rdio-scanner-darwin-arm64-v6.1.16.zip > ~/Downloads/rdio-scanner-darwin-arm64-v6.2.0.zip
Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.1.16.zip Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.2.0.zip
inflating: rdio-scanner inflating: rdio-scanner
inflating: rdio-scanner.pdf inflating: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@macos rdio-scanner % ./rdio-scanner rdio@macos rdio-scanner % ./rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:38:06 server started 2022/03/25 08:38:06 server started
2022/03/17 08:38:06 main interface at http://macos.local:3000 2022/03/25 08:38:06 main interface at http://macos.local:3000
2022/03/17 08:38:06 admin interface at http://macos.local:3000/admin 2022/03/25 08:38:06 admin interface at http://macos.local:3000/admin
4. Access the administrative dashboard to finalize the configuration. 4. Access the administrative dashboard to finalize the configuration.
@ -77,11 +77,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
rdio@macos rdio-scanner % ./rdio-scanner --listen :80 rdio@macos rdio-scanner % ./rdio-scanner --listen :80
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:48:03 server started 2022/03/25 08:48:03 server started
2022/03/17 08:48:03 main interface at http://macos.local 2022/03/25 08:48:03 main interface at http://macos.local
2022/03/17 08:48:03 admin interface at http://macos.local/admin 2022/03/25 08:48:03 admin interface at http://macos.local/admin
## Listening on a SSL port ## Listening on a SSL port
@ -95,12 +95,12 @@ You can use your own SSL certificates that match your domain name with `-ssl_cer
> -ssl_key_file mykey.key \ > -ssl_key_file mykey.key \
> -ssl_listen :443 > -ssl_listen :443
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:50:58 server started 2022/03/25 08:50:58 server started
2022/03/17 08:50:58 main interface at http://macos.local 2022/03/25 08:50:58 main interface at http://macos.local
2022/03/17 08:50:58 main interface at https://macos.local 2022/03/25 08:50:58 main interface at https://macos.local
2022/03/17 08:50:58 admin interface at https://macos.local/admin 2022/03/25 08:50:58 admin interface at https://macos.local/admin
If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal. If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal.
@ -118,7 +118,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_auto_cert mydomain.com \ > -ssl_auto_cert mydomain.com \
> -ssl_listen :443 \ > -ssl_listen :443 \
> -config_save > -config_save
2022/03/17 08:52:24 rdio-scanner.ini file created 2022/03/25 08:52:24 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list. All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -132,12 +132,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
rdio@macos rdio-scanner % ./rdio-scanner rdio@macos rdio-scanner % ./rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:54:08 server started 2022/03/25 08:54:08 server started
2022/03/17 08:54:08 main interface at http://macos.local 2022/03/25 08:54:08 main interface at http://macos.local
2022/03/17 08:54:08 main interface at https://macos.local 2022/03/25 08:54:08 main interface at https://macos.local
2022/03/17 08:54:08 admin interface at https://macos.local/admin 2022/03/25 08:54:08 admin interface at https://macos.local/admin
## Install Rdio Scanner as a service ## Install Rdio Scanner as a service
@ -206,9 +206,11 @@ You can ask your questions or post your comments on the [Rdio Scanner Discussion
# Show your appreciation, support the author # Show your appreciation, support the author
If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated. If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner/stargazers)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated.
If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[consider sponsoring the project](https://github.com/sponsors/chuot)** to help support continued development. If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[sponsor the project](https://github.com/sponsors/chuot)** to help support continued development.
[![Follow us on Twitter](../images/twitter-badge.png?raw=true)](https://twitter.com/RdioScanner)
# Commercial support # Commercial support

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@pc-freebsd:~ $ mkdir rdio-scanner rdio@pc-freebsd:~ $ mkdir rdio-scanner
rdio@pc-freebsd:~ $ cd rdio-scanner rdio@pc-freebsd:~ $ cd rdio-scanner
rdio@pc-freebsd:~/rdio-scanner $ unzip \ rdio@pc-freebsd:~/rdio-scanner $ unzip \
> ~/rdio-scanner-freebsd-amd64-v6.1.16.zip > ~/rdio-scanner-freebsd-amd64-v6.2.0.zip
Archive: ../rdio-scanner-freebsd-amd64-v6.1.16.zip Archive: ../rdio-scanner-freebsd-amd64-v6.2.0.zip
extracting: rdio-scanner extracting: rdio-scanner
extracting: rdio-scanner.pdf extracting: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@pc-freebsd:~/rdio-scanner $ ./rdio-scanner rdio@pc-freebsd:~/rdio-scanner $ ./rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:16:36 server started 2022/03/25 08:16:36 server started
2022/03/17 08:16:36 main interface at http://pc-freebsd:3000 2022/03/25 08:16:36 main interface at http://pc-freebsd:3000
2022/03/17 08:16:36 admin interface at http://pc-freebsd:3000/admin 2022/03/25 08:16:36 admin interface at http://pc-freebsd:3000/admin
4. Access the administrative dashboard to finalize the configuration. 4. Access the administrative dashboard to finalize the configuration.
@ -81,11 +81,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
Password: Password:
root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner -listen :80 root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner -listen :80
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 08:19:38 server started 2022/03/25 08:19:38 server started
2022/03/17 08:19:38 main interface at http://pc-freebsd 2022/03/25 08:19:38 main interface at http://pc-freebsd
2022/03/17 08:19:38 admin interface at http://pc-freebsd/admin 2022/03/25 08:19:38 admin interface at http://pc-freebsd/admin
## Listening on a SSL port ## Listening on a SSL port
@ -101,12 +101,12 @@ You can use your own SSL certificates that match your domain name with `-ssl_cer
> -ssl_key_file mykey.key \ > -ssl_key_file mykey.key \
> -ssl_listen :443 > -ssl_listen :443
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 10:34:29 server started 2022/03/25 10:34:29 server started
2022/03/17 10:34:29 main interface at http://pc-freebsd 2022/03/25 10:34:29 main interface at http://pc-freebsd
2022/03/17 10:34:29 main interface at https://pc-freebsd 2022/03/25 10:34:29 main interface at https://pc-freebsd
2022/03/17 10:34:29 admin interface at https://pc-freebsd/admin 2022/03/25 10:34:29 admin interface at https://pc-freebsd/admin
If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal. If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal.
@ -126,7 +126,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_auto_cert mydomain.com \ > -ssl_auto_cert mydomain.com \
> -ssl_listen :443 \ > -ssl_listen :443 \
> -config_save > -config_save
2022/03/17 10:37:00 rdio-scanner.ini file created 2022/03/25 10:37:00 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list. All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -142,12 +142,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
Password: Password:
root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 10:38:28 server started 2022/03/25 10:38:28 server started
2022/03/17 10:38:29 main interface at http://pc-freebsd 2022/03/25 10:38:29 main interface at http://pc-freebsd
2022/03/17 10:38:29 main interface at https://pc-freebsd 2022/03/25 10:38:29 main interface at https://pc-freebsd
2022/03/17 10:38:29 admin interface at https://pc-freebsd/admin 2022/03/25 10:38:29 admin interface at https://pc-freebsd/admin
## Install Rdio Scanner as a service ## Install Rdio Scanner as a service
@ -219,9 +219,11 @@ You can ask your questions or post your comments on the [Rdio Scanner Discussion
# Show your appreciation, support the author # Show your appreciation, support the author
If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated. If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner/stargazers)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated.
If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[consider sponsoring the project](https://github.com/sponsors/chuot)** to help support continued development. If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[sponsor the project](https://github.com/sponsors/chuot)** to help support continued development.
[![Follow us on Twitter](../images/twitter-badge.png?raw=true)](https://twitter.com/RdioScanner)
# Commercial support # Commercial support

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
[rdio@pc-linux ~]$ mkdir rdio-scanner [rdio@pc-linux ~]$ mkdir rdio-scanner
[rdio@pc-linux ~]$ cd rdio-scanner [rdio@pc-linux ~]$ cd rdio-scanner
[rdio@pc-linux rdio-scanner]$ unzip \ [rdio@pc-linux rdio-scanner]$ unzip \
> ~/Downloads/rdio-scanner-linux-amd64-v6.1.16.zip > ~/Downloads/rdio-scanner-linux-amd64-v6.2.0.zip
Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.1.16.zip Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.2.0.zip
inflating: rdio-scanner inflating: rdio-scanner
inflating: rdio-scanner.pdf inflating: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
[rdio@pc-linux rdio-scanner]$ ./rdio-scanner [rdio@pc-linux rdio-scanner]$ ./rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 09:11:48 server started 2022/03/25 09:11:48 server started
2022/03/17 09:11:48 main interface at http://pc-linux:3000 2022/03/25 09:11:48 main interface at http://pc-linux:3000
2022/03/17 09:11:48 admin interface at http://pc-linux:3000/admin 2022/03/25 09:11:48 admin interface at http://pc-linux:3000/admin
4. Access the administrative dashboard to finalize the configuration. 4. Access the administrative dashboard to finalize the configuration.
@ -78,11 +78,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
[rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner -listen :80 [rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner -listen :80
[sudo] password for rdio: [sudo] password for rdio:
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 09:14:00 server started 2022/03/25 09:14:00 server started
2022/03/17 09:14:00 main interface at http://pc-linux 2022/03/25 09:14:00 main interface at http://pc-linux
2022/03/17 09:14:00 admin interface at http://pc-linux/admin 2022/03/25 09:14:00 admin interface at http://pc-linux/admin
## Listening on a SSL port ## Listening on a SSL port
@ -97,12 +97,12 @@ You can use your own SSL certificates that match your domain name with `-ssl_cer
> -ssl_listen :443 > -ssl_listen :443
[sudo] password for rdio: [sudo] password for rdio:
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 09:16:47 server started 2022/03/25 09:16:47 server started
2022/03/17 09:16:47 main interface at http://pc-linux 2022/03/25 09:16:47 main interface at http://pc-linux
2022/03/17 09:16:47 main interface at https://pc-linux 2022/03/25 09:16:47 main interface at https://pc-linux
2022/03/17 09:16:47 admin interface at https://pc-linux/admin 2022/03/25 09:16:47 admin interface at https://pc-linux/admin
If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal. If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal.
@ -120,7 +120,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_auto_cert mydomain.com \ > -ssl_auto_cert mydomain.com \
> -ssl_listen :443 \ > -ssl_listen :443 \
> -config_save > -config_save
2022/03/17 09:19:29 rdio-scanner.ini file created 2022/03/25 09:19:29 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list. All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -135,12 +135,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
[rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner [rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner
[sudo] Mot de passe de rdio : [sudo] Mot de passe de rdio :
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 09:20:40 server started 2022/03/25 09:20:40 server started
2022/03/17 09:20:40 main interface at http://pc-linux 2022/03/25 09:20:40 main interface at http://pc-linux
2022/03/17 09:20:40 main interface at https://pc-linux 2022/03/25 09:20:40 main interface at https://pc-linux
2022/03/17 09:20:40 admin interface at https://pc-linux/admin 2022/03/25 09:20:40 admin interface at https://pc-linux/admin
## Install Rdio Scanner as a service ## Install Rdio Scanner as a service
@ -209,9 +209,11 @@ You can ask your questions or post your comments on the [Rdio Scanner Discussion
# Show your appreciation, support the author # Show your appreciation, support the author
If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated. If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner/stargazers)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated.
If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[consider sponsoring the project](https://github.com/sponsors/chuot)** to help support continued development. If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[sponsor the project](https://github.com/sponsors/chuot)** to help support continued development.
[![Follow us on Twitter](../images/twitter-badge.png?raw=true)](https://twitter.com/RdioScanner)
# Commercial support # Commercial support

View file

@ -44,7 +44,7 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
C:\Users\rdio> cd rdio-scanner C:\Users\rdio> cd rdio-scanner
C:\Users\rdio\rdio-scanner> tar -xvf ^ C:\Users\rdio\rdio-scanner> tar -xvf ^
..\downloads\rdio-scanner-windows-amd64-v6.1.16.zip ..\downloads\rdio-scanner-windows-amd64-v6.2.0.zip
x rdio-scanner.exe x rdio-scanner.exe
x rdio-scanner.pdf x rdio-scanner.pdf
@ -52,11 +52,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
C:\Users\rdio\rdio-scanner>rdio-scanner C:\Users\rdio\rdio-scanner>rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 13:48:48 server started 2022/03/25 13:48:48 server started
2022/03/17 13:48:48 main interface at http://pc-windows:3000 2022/03/25 13:48:48 main interface at http://pc-windows:3000
2022/03/17 13:48:48 admin interface at http://pc-windows:3000/admin 2022/03/25 13:48:48 admin interface at http://pc-windows:3000/admin
4. Access the administrative dashboard to finalize the configuration. 4. Access the administrative dashboard to finalize the configuration.
@ -78,11 +78,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
C:\Users\rdio\rdio-scanner>rdio-scanner -listen :80 C:\Users\rdio\rdio-scanner>rdio-scanner -listen :80
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 10:53:31 server started 2022/03/25 10:53:31 server started
2022/03/17 10:53:31 main interface at http://pc-windows 2022/03/25 10:53:31 main interface at http://pc-windows
2022/03/17 10:53:31 admin interface at http://pc-windows/admin 2022/03/25 10:53:31 admin interface at http://pc-windows/admin
## Listening on a SSL port ## Listening on a SSL port
@ -96,12 +96,12 @@ You can use your own SSL certificates that match your domain name with `-ssl_cer
-ssl_key_file meykey.key ^ -ssl_key_file meykey.key ^
-ssl_listen :443 -ssl_listen :443
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 11:05:43 server started 2022/03/25 11:05:43 server started
2022/03/17 11:05:43 main interface at http://pc-windows 2022/03/25 11:05:43 main interface at http://pc-windows
2022/03/17 11:05:43 main interface at https://pc-windows 2022/03/25 11:05:43 main interface at https://pc-windows
2022/03/17 11:05:43 admin interface at https://pc-windows/admin 2022/03/25 11:05:43 admin interface at https://pc-windows/admin
If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal. If you don't want to worry about SSL certificates, you can use the built-in Let's Encrypt auto-cert feature. This requires that you have both port 80 (HTTP) and port 443 (HTTPS) open to the world. Also, your domain name should point to your IP address where [Rdio Scanner](https://github.com/chuot/rdio-scanner/) is running. The advantage of this approach is that everything is done automatically, no certificate request, no certificate renewal.
@ -119,7 +119,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
-ssl_auto_cert mydomain.com ^ -ssl_auto_cert mydomain.com ^
-ssl_listen :443 ^ -ssl_listen :443 ^
-config_save -config_save
2022/03/17 11:08:28 rdio-scanner.ini file created 2022/03/25 11:08:28 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list. All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -133,12 +133,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
C:\Users\rdio\rdio-scanner>rdio-scanner C:\Users\rdio\rdio-scanner>rdio-scanner
Rdio Scanner v6.1.16 Rdio Scanner v6.2.0
---------------------------------- ----------------------------------
2022/03/17 11:11:28 server started 2022/03/25 11:11:28 server started
2022/03/17 11:11:28 main interface at http://pc-windows 2022/03/25 11:11:28 main interface at http://pc-windows
2022/03/17 11:11:28 main interface at https://pc-windows 2022/03/25 11:11:28 main interface at https://pc-windows
2022/03/17 11:11:28 admin interface at https://pc-windows/admin 2022/03/25 11:11:28 admin interface at https://pc-windows/admin
\pagebreak{} \pagebreak{}
@ -207,9 +207,11 @@ You can ask your questions or post your comments on the [Rdio Scanner Discussion
# Show your appreciation, support the author # Show your appreciation, support the author
If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated. If you like [Rdio Scanner](https://github.com/chuot/rdio-scanner), **[consider starring the GitHub repository](https://github.com/chuot/rdio-scanner/stargazers)** to show you appreciation to the author for his hard work. It cost nothing but is really appreciated.
If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[consider sponsoring the project](https://github.com/sponsors/chuot)** to help support continued development. If you use [Rdio Scanner](https://github.com/chuot/rdio-scanner) for commercial purposes or derive income from it, **[sponsor the project](https://github.com/sponsors/chuot)** to help support continued development.
[![Follow us on Twitter](../images/twitter-badge.png?raw=true)](https://twitter.com/RdioScanner)
# Commercial support # Commercial support

View file

@ -49,6 +49,11 @@ func (client *Client) Init(controller *Controller, conn *websocket.Conn) error {
return errors.New("client.init: no websocket connection") return errors.New("client.init: no websocket connection")
} }
if controller.Clients.Count() >= int(controller.Options.MaxClients) {
conn.Close()
return nil
}
client.Access = &Access{} client.Access = &Access{}
client.Controller = controller client.Controller = controller
client.Conn = conn client.Conn = conn
@ -98,6 +103,9 @@ func (client *Client) Init(controller *Controller, conn *websocket.Conn) error {
defer func() { defer func() {
ticker.Stop() ticker.Stop()
timer.Stop() timer.Stop()
client.Conn.WriteMessage(websocket.CloseMessage, []byte{})
client.Conn.Close()
}() }()
for { for {
@ -148,16 +156,24 @@ func (client *Client) SendConfig(groups *Groups, options *Options, systems *Syst
client.Send <- &Message{ client.Send <- &Message{
Command: MessageCommandConfig, Command: MessageCommandConfig,
Payload: map[string]interface{}{ Payload: map[string]interface{}{
"dimmerDelay": options.DimmerDelay, "dimmerDelay": options.DimmerDelay,
"groups": client.GroupsMap, "groups": client.GroupsMap,
"keypadBeeps": GetKeypadBeeps(options), "keypadBeeps": GetKeypadBeeps(options),
"systems": client.SystemsMap, "showListenersCount": options.ShowListenersCount,
"tags": client.TagsMap, "systems": client.SystemsMap,
"tagsToggle": options.TagsToggle, "tags": client.TagsMap,
"tagsToggle": options.TagsToggle,
}, },
} }
} }
func (client *Client) SendListenersCount(count int) {
client.Send <- &Message{
Command: MessagecommandListenersCount,
Payload: count,
}
}
type Clients struct { type Clients struct {
Map map[*Client]bool Map map[*Client]bool
mutex sync.Mutex mutex sync.Mutex
@ -220,6 +236,19 @@ func (clients *Clients) EmitConfig(groups *Groups, options *Options, systems *Sy
} else { } else {
c.SendConfig(groups, options, systems, tags) c.SendConfig(groups, options, systems, tags)
} }
if options.ShowListenersCount {
c.SendListenersCount(len(clients.Map))
}
}
}
func (clients *Clients) EmitListenersCount() {
clients.mutex.Lock()
defer clients.mutex.Unlock()
for c := range clients.Map {
c.SendListenersCount(len(clients.Map))
} }
} }
@ -230,7 +259,4 @@ func (clients *Clients) Remove(client *Client) {
delete(clients.Map, client) delete(clients.Map, client)
close(client.Send) close(client.Send)
client.Conn.WriteMessage(websocket.CloseMessage, []byte{})
client.Conn.Close()
} }

View file

@ -312,12 +312,12 @@ func (controller *Controller) IngestCall(call *Call) {
} }
switch v := call.units.(type) { switch v := call.units.(type) {
case Units: case *Units:
populated = true populated = true
if system.Units == nil { if system.Units == nil {
system.Units = NewUnits() system.Units = NewUnits()
} }
system.Units.Merge(&v) system.Units.Merge(v)
} }
} }
@ -619,22 +619,28 @@ func (controller *Controller) Start() error {
go func() { go func() {
var timer *time.Timer var timer *time.Timer
logClientsCount := func() { doClientsCount := func() {
if timer != nil { if timer != nil {
timer.Stop() timer.Stop()
} }
timer = time.AfterFunc(time.Second, controller.LogClientsCount) timer = time.AfterFunc(time.Second, func() {
controller.LogClientsCount()
if controller.Options.ShowListenersCount {
controller.Clients.EmitListenersCount()
}
})
} }
for { for {
select { select {
case client := <-controller.Register: case client := <-controller.Register:
controller.Clients.Add(client) controller.Clients.Add(client)
logClientsCount() doClientsCount()
case client := <-controller.Unregister: case client := <-controller.Unregister:
controller.Clients.Remove(client) controller.Clients.Remove(client)
logClientsCount() doClientsCount()
} }
} }
}() }()

View file

@ -56,8 +56,10 @@ type DefaultOptions struct {
disableDuplicateDetection bool disableDuplicateDetection bool
duplicateDetectionTimeFrame uint duplicateDetectionTimeFrame uint
keypadBeeps string keypadBeeps string
maxClients uint
pruneDays uint pruneDays uint
searchPatchedTalkgroups bool searchPatchedTalkgroups bool
showListenersCount bool
sortTalkgroups bool sortTalkgroups bool
tagsToggle bool tagsToggle bool
} }
@ -96,8 +98,10 @@ var defaults Defaults = Defaults{
disableDuplicateDetection: false, disableDuplicateDetection: false,
duplicateDetectionTimeFrame: 500, duplicateDetectionTimeFrame: 500,
keypadBeeps: "uniden", keypadBeeps: "uniden",
maxClients: 200,
pruneDays: 7, pruneDays: 7,
searchPatchedTalkgroups: false, searchPatchedTalkgroups: false,
showListenersCount: false,
sortTalkgroups: false, sortTalkgroups: false,
tagsToggle: false, tagsToggle: false,
}, },

View file

@ -10,9 +10,9 @@ require (
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/kardianos/service v1.2.1 github.com/kardianos/service v1.2.1
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
gopkg.in/ini.v1 v1.66.4 gopkg.in/ini.v1 v1.66.4
modernc.org/sqlite v1.15.2 modernc.org/sqlite v1.15.3
) )
require ( require (
@ -22,16 +22,16 @@ require (
github.com/stretchr/testify v1.7.0 // indirect github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf // indirect golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.10 // indirect golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.35.24 // indirect modernc.org/cc/v3 v3.35.24 // indirect
modernc.org/ccgo/v3 v3.15.17 // indirect modernc.org/ccgo/v3 v3.15.17 // indirect
modernc.org/libc v1.14.11 // indirect modernc.org/libc v1.14.12 // indirect
modernc.org/mathutil v1.4.1 // indirect modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.0.6 // indirect modernc.org/memory v1.0.7 // indirect
modernc.org/opt v0.1.1 // indirect modernc.org/opt v0.1.1 // indirect
modernc.org/strutil v1.1.1 // indirect modernc.org/strutil v1.1.1 // indirect
modernc.org/token v1.0.0 // indirect modernc.org/token v1.0.0 // indirect

View file

@ -38,8 +38,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
@ -68,8 +68,8 @@ golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -209,8 +209,9 @@ modernc.org/libc v1.14.6/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/libc v1.14.7/go.mod h1:f8xfWXW8LW41qb4X5+huVQo5dcfPlq7Cbny2TDheMv0= modernc.org/libc v1.14.7/go.mod h1:f8xfWXW8LW41qb4X5+huVQo5dcfPlq7Cbny2TDheMv0=
modernc.org/libc v1.14.8/go.mod h1:9+JCLb1MWSY23smyOpIPbd5ED+rSS/ieiDWUpdyO3mo= modernc.org/libc v1.14.8/go.mod h1:9+JCLb1MWSY23smyOpIPbd5ED+rSS/ieiDWUpdyO3mo=
modernc.org/libc v1.14.10/go.mod h1:y1MtIWhwpJFpLYm6grAThtuXJKEsY6xkdZmXbRngIdo= modernc.org/libc v1.14.10/go.mod h1:y1MtIWhwpJFpLYm6grAThtuXJKEsY6xkdZmXbRngIdo=
modernc.org/libc v1.14.11 h1:ivxNmUkfp5iSGAGMIjylvx5R53s6QTJW9qUru1yrnk4=
modernc.org/libc v1.14.11/go.mod h1:l5/Mz/GrZwOqzwRHA3abgSCnSeJzzTl+Ify0bAwKbAw= modernc.org/libc v1.14.11/go.mod h1:l5/Mz/GrZwOqzwRHA3abgSCnSeJzzTl+Ify0bAwKbAw=
modernc.org/libc v1.14.12 h1:pUBZTYoISfbb4pCf4PECENpbvwDBxeKc+/dS9LyOWFM=
modernc.org/libc v1.14.12/go.mod h1:fJdoe23MHu2ruPQkFPPqCpToDi5cckzsbmkI6Ez0LqQ=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
@ -218,12 +219,13 @@ modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/memory v1.0.6 h1:5IaT/LChMrMdxLCy/a4qmb+7SzGiU8/ozPgkEOrfvFw=
modernc.org/memory v1.0.6/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.0.6/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.0.7 h1:UE3cxTRFa5tfUibAV7Jqq8P7zRY0OlJg+yWVIIaluEE=
modernc.org/memory v1.0.7/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.15.2 h1:Es0SrEJUQHH7rt6uC/Zh2gHQ0AUhgB+F2RQqpXf3MNs= modernc.org/sqlite v1.15.3 h1:3C4AWicF7S5vUUFJuBi7Ws8eWlPjqyo/c4Z1UGYBbyg=
modernc.org/sqlite v1.15.2/go.mod h1:2P9bWfawhYMpYsBELqKREE+LFZo4uPApOuqszlZ7QX8= modernc.org/sqlite v1.15.3/go.mod h1:J7GAPbk8Txp0DJnT8TGwpUqJW0Z1cK2YpzjoXaZRU8k=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.11.2 h1:mXpsx3AZqJt83uDiFu9UYQVBjNjaWKGCF1YDSlpCL6Y= modernc.org/tcl v1.11.2 h1:mXpsx3AZqJt83uDiFu9UYQVBjNjaWKGCF1YDSlpCL6Y=

View file

@ -20,17 +20,18 @@ import (
) )
const ( const (
MessageCommandCall = "CAL" MessageCommandCall = "CAL"
MessageCommandConfig = "CFG" MessageCommandConfig = "CFG"
MessageCommandExpired = "XPR" MessageCommandExpired = "XPR"
MessageCommandIOS = "IOS" MessageCommandIOS = "IOS"
MessageCommandListCall = "LCL" MessageCommandListCall = "LCL"
MessageCommandLivefeedMap = "LFM" MessagecommandListenersCount = "LSC"
MessageCommandMax = "MAX" MessageCommandLivefeedMap = "LFM"
MessageCommandPin = "PIN" MessageCommandMax = "MAX"
MessageCommandPushId = "PID" MessageCommandPin = "PIN"
MessageCommandServer = "SRV" MessageCommandPushId = "PID"
MessageCommandVersion = "VER" MessageCommandServer = "SRV"
MessageCommandVersion = "VER"
) )
type Message struct { type Message struct {

View file

@ -31,8 +31,10 @@ type Options struct {
DisableDuplicateDetection bool `json:"disableDuplicateDetection"` DisableDuplicateDetection bool `json:"disableDuplicateDetection"`
DuplicateDetectionTimeFrame uint `json:"duplicateDetectionTimeFrame"` DuplicateDetectionTimeFrame uint `json:"duplicateDetectionTimeFrame"`
KeypadBeeps string `json:"keypadBeeps"` KeypadBeeps string `json:"keypadBeeps"`
MaxClients uint `json:"maxClients"`
PruneDays uint `json:"pruneDays"` PruneDays uint `json:"pruneDays"`
SearchPatchedTalkgroups bool `json:"searchPatchedTalkgroups"` SearchPatchedTalkgroups bool `json:"searchPatchedTalkgroups"`
ShowListenersCount bool `json:"showListenersCount"`
SortTalkgroups bool `json:"sortTalkgroups"` SortTalkgroups bool `json:"sortTalkgroups"`
TagsToggle bool `json:"tagsToggle"` TagsToggle bool `json:"tagsToggle"`
adminPassword string adminPassword string
@ -93,6 +95,13 @@ func (options *Options) FromMap(m map[string]interface{}) {
options.KeypadBeeps = defaults.options.keypadBeeps options.KeypadBeeps = defaults.options.keypadBeeps
} }
switch v := m["maxClients"].(type) {
case float64:
options.MaxClients = uint(v)
default:
options.MaxClients = defaults.options.maxClients
}
switch v := m["pruneDays"].(type) { switch v := m["pruneDays"].(type) {
case float64: case float64:
options.PruneDays = uint(v) options.PruneDays = uint(v)
@ -107,6 +116,13 @@ func (options *Options) FromMap(m map[string]interface{}) {
options.SearchPatchedTalkgroups = defaults.options.searchPatchedTalkgroups options.SearchPatchedTalkgroups = defaults.options.searchPatchedTalkgroups
} }
switch v := m["showListenersCount"].(type) {
case bool:
options.ShowListenersCount = v
default:
options.ShowListenersCount = defaults.options.showListenersCount
}
switch v := m["sortTalkgroups"].(type) { switch v := m["sortTalkgroups"].(type) {
case bool: case bool:
options.SortTalkgroups = v options.SortTalkgroups = v
@ -142,8 +158,10 @@ func (options *Options) Read(db *Database) error {
options.DisableDuplicateDetection = defaults.options.disableDuplicateDetection options.DisableDuplicateDetection = defaults.options.disableDuplicateDetection
options.DuplicateDetectionTimeFrame = defaults.options.duplicateDetectionTimeFrame options.DuplicateDetectionTimeFrame = defaults.options.duplicateDetectionTimeFrame
options.KeypadBeeps = defaults.options.keypadBeeps options.KeypadBeeps = defaults.options.keypadBeeps
options.MaxClients = defaults.options.maxClients
options.PruneDays = defaults.options.pruneDays options.PruneDays = defaults.options.pruneDays
options.SearchPatchedTalkgroups = defaults.options.searchPatchedTalkgroups options.SearchPatchedTalkgroups = defaults.options.searchPatchedTalkgroups
options.ShowListenersCount = defaults.options.showListenersCount
options.SortTalkgroups = defaults.options.sortTalkgroups options.SortTalkgroups = defaults.options.sortTalkgroups
options.TagsToggle = defaults.options.tagsToggle options.TagsToggle = defaults.options.tagsToggle
@ -216,6 +234,11 @@ func (options *Options) Read(db *Database) error {
options.KeypadBeeps = v options.KeypadBeeps = v
} }
switch v := v["maxClients"].(type) {
case float64:
options.MaxClients = uint(v)
}
switch v := v["pruneDays"].(type) { switch v := v["pruneDays"].(type) {
case float64: case float64:
options.PruneDays = uint(v) options.PruneDays = uint(v)
@ -226,6 +249,11 @@ func (options *Options) Read(db *Database) error {
options.SearchPatchedTalkgroups = v options.SearchPatchedTalkgroups = v
} }
switch v := v["showListenersCount"].(type) {
case bool:
options.ShowListenersCount = v
}
switch v := v["sortTalkgroups"].(type) { switch v := v["sortTalkgroups"].(type) {
case bool: case bool:
options.SortTalkgroups = v options.SortTalkgroups = v
@ -300,8 +328,10 @@ func (options *Options) Write(db *Database) error {
"disableDuplicateDetection": options.DisableDuplicateDetection, "disableDuplicateDetection": options.DisableDuplicateDetection,
"duplicateDetectionTimeFrame": options.DuplicateDetectionTimeFrame, "duplicateDetectionTimeFrame": options.DuplicateDetectionTimeFrame,
"keypadBeeps": options.KeypadBeeps, "keypadBeeps": options.KeypadBeeps,
"maxClients": options.MaxClients,
"pruneDays": options.PruneDays, "pruneDays": options.PruneDays,
"searchPatchedTalkgroups": options.SearchPatchedTalkgroups, "searchPatchedTalkgroups": options.SearchPatchedTalkgroups,
"showListenersCount": options.ShowListenersCount,
"sortTalkgroups": options.SortTalkgroups, "sortTalkgroups": options.SortTalkgroups,
"tagsToggle": options.TagsToggle, "tagsToggle": options.TagsToggle,
}); err != nil { }); err != nil {

View file

@ -41,13 +41,23 @@ func ParseSdrTrunkMeta(call *Call, controller *Controller) error {
return err return err
} }
s = regexp.MustCompile(`^([0-9]+)$`).FindStringSubmatch(m.Artist()) s = regexp.MustCompile(`^([0-9]+) ?(.+)$`).FindStringSubmatch(m.Artist())
if len(s) == 2 { if len(s) >= 2 {
if i, err = strconv.Atoi(s[1]); err != nil { if i, err = strconv.Atoi(s[1]); err != nil {
return err return err
} }
if i > 0 { if i > 0 {
call.Source = uint(i) call.Source = uint(i)
if len(s) == 3 {
if call.units == nil {
call.units = NewUnits()
}
switch units := call.units.(type) {
case *Units:
units.Add(uint(i), s[2])
}
}
} }
} }

View file

@ -15,4 +15,4 @@
package main package main
const Version = "6.1.16" const Version = "6.2.0"