├── ndsweb
├── src
│ ├── app
│ │ ├── app.component.scss
│ │ ├── components
│ │ │ ├── view-features
│ │ │ │ ├── view-features.component.scss
│ │ │ │ ├── view-features.component.html
│ │ │ │ └── view-features.component.ts
│ │ │ ├── index.ts
│ │ │ ├── reorder-columns
│ │ │ │ ├── reorder-columns.component.scss
│ │ │ │ ├── reorder-columns.component.html
│ │ │ │ └── reorder-columns.component.ts
│ │ │ └── monitor
│ │ │ │ └── monitor.component.scss
│ │ ├── app.component.html
│ │ ├── services
│ │ │ ├── index.ts
│ │ │ └── monitor.service.ts
│ │ ├── state
│ │ │ ├── index.ts
│ │ │ └── monitor.state.ts
│ │ ├── containers
│ │ │ ├── index.ts
│ │ │ └── monitor
│ │ │ │ ├── monitor-container.component.scss
│ │ │ │ ├── monitor-container.component.html
│ │ │ │ └── monitor-container.component.ts
│ │ ├── models.ts
│ │ ├── pipes
│ │ │ ├── index.ts
│ │ │ ├── format-delta.pipe.ts
│ │ │ └── format-size.pipe.ts
│ │ ├── actions
│ │ │ ├── index.ts
│ │ │ └── monitor.actions.ts
│ │ ├── tokens.ts
│ │ ├── app.routes.ts
│ │ ├── app.component.ts
│ │ ├── app.config.ts
│ │ └── dialogs
│ │ │ ├── view-features-dialog.component.ts
│ │ │ ├── reorder-columns-dialog.component.ts
│ │ │ └── confirm-dialog.component.ts
│ ├── test-setup.ts
│ ├── environments
│ │ ├── environment.ts
│ │ └── environment.prod.ts
│ ├── styles.scss
│ ├── main.ts
│ ├── index.html
│ └── themes.scss
├── .prettierrc
├── public
│ └── favicon.ico
├── readme-compile.png
├── jest.preset.js
├── .prettierignore
├── .vscode
│ └── extensions.json
├── tsconfig.editor.json
├── tsconfig.app.json
├── tsconfig.spec.json
├── .gitignore
├── jest.config.ts
├── eslint.config.js
├── tsconfig.json
├── nx.json
├── package.json
├── project.json
└── README.md
├── media
└── mp4
│ ├── rickroll.mp4
│ ├── triangle.mp4
│ └── goldendollars.mp4
├── .gitignore
├── secrets.h.example
├── tests
├── ntest.sh
├── ntest.sht
└── Makefile
├── .vscode
├── tasks.json
├── c_cpp_properties.json
├── launch.json
└── settings.json
├── monitor
├── Makefile
├── main.cpp
└── monitor.h
├── ledeffectbase.h
├── effects
├── misceffects.h
├── colorwaveeffect.h
├── bouncingballeffect.h
├── starfield.h
├── paletteeffect.h
├── fireworkseffect.h
└── videoeffect.h
├── Makefile
├── .github
└── workflows
│ └── CI.yml
├── global.h
├── main.cpp
├── palette.h
├── canvas.h
├── schedule.h
├── sample_config.json
├── basegraphics.h
├── README.md
├── utilities.h
├── ledfeature.h
├── interfaces.h
└── effectsmanager.h
/ndsweb/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/view-features/view-features.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ndsweb/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ndsweb/src/app/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './monitor.service';
2 |
--------------------------------------------------------------------------------
/ndsweb/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "tabWidth": 4
4 | }
5 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './monitor/monitor.component';
--------------------------------------------------------------------------------
/ndsweb/src/app/state/index.ts:
--------------------------------------------------------------------------------
1 | export { MonitorState } from './monitor.state';
2 |
--------------------------------------------------------------------------------
/ndsweb/src/app/containers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './monitor/monitor-container.component'
--------------------------------------------------------------------------------
/media/mp4/rickroll.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlummersSoftwareLLC/NDSCPP/HEAD/media/mp4/rickroll.mp4
--------------------------------------------------------------------------------
/media/mp4/triangle.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlummersSoftwareLLC/NDSCPP/HEAD/media/mp4/triangle.mp4
--------------------------------------------------------------------------------
/ndsweb/src/app/models.ts:
--------------------------------------------------------------------------------
1 | export interface Column {
2 | key: string;
3 | value: string;
4 | }
5 |
--------------------------------------------------------------------------------
/ndsweb/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlummersSoftwareLLC/NDSCPP/HEAD/ndsweb/public/favicon.ico
--------------------------------------------------------------------------------
/ndsweb/readme-compile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlummersSoftwareLLC/NDSCPP/HEAD/ndsweb/readme-compile.png
--------------------------------------------------------------------------------
/ndsweb/src/app/pipes/index.ts:
--------------------------------------------------------------------------------
1 | export * from './format-size.pipe';
2 | export * from './format-delta.pipe';
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | secrets.h
2 | config.led
3 | .deps
4 | *.o
5 | *.tmp
6 | ndscpp
7 | monitor/ledmon
8 | tests/tests
9 | cpr
--------------------------------------------------------------------------------
/media/mp4/goldendollars.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlummersSoftwareLLC/NDSCPP/HEAD/media/mp4/goldendollars.mp4
--------------------------------------------------------------------------------
/ndsweb/src/app/actions/index.ts:
--------------------------------------------------------------------------------
1 | import * as MonitorActions from './monitor.actions';
2 | export { MonitorActions };
--------------------------------------------------------------------------------
/ndsweb/src/app/components/reorder-columns/reorder-columns.component.scss:
--------------------------------------------------------------------------------
1 | .reorder {
2 | cursor: grab;
3 | }
4 |
--------------------------------------------------------------------------------
/ndsweb/jest.preset.js:
--------------------------------------------------------------------------------
1 | const nxPreset = require('@nx/jest/preset').default;
2 |
3 | module.exports = { ...nxPreset };
4 |
--------------------------------------------------------------------------------
/ndsweb/src/app/tokens.ts:
--------------------------------------------------------------------------------
1 | import { InjectionToken } from "@angular/core";
2 |
3 | export const APP_SERVER_URL = new InjectionToken('AppServerUrl');
--------------------------------------------------------------------------------
/secrets.h.example:
--------------------------------------------------------------------------------
1 | // NOTE: Copy this file to secrets.h and enter your actual values there, NOT here!
2 |
3 | #define API_KEY "Your AV API key"
4 |
--------------------------------------------------------------------------------
/ndsweb/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 | /dist
3 | /coverage
4 | /.nx/cache
5 | /.nx/workspace-data
6 | .angular
7 |
--------------------------------------------------------------------------------
/ndsweb/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
2 |
3 | setupZoneTestEnv({
4 | errorOnUnknownElements: true,
5 | errorOnUnknownProperties: true,
6 | });
7 |
--------------------------------------------------------------------------------
/ndsweb/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "nrwl.angular-console",
4 | "esbenp.prettier-vscode",
5 | "dbaeumer.vscode-eslint",
6 | "firsttris.vscode-jest-runner"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/ndsweb/tsconfig.editor.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src/**/*.ts"],
4 | "compilerOptions": {},
5 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
6 | }
7 |
--------------------------------------------------------------------------------
/ndsweb/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: false,
3 |
4 | buildVersion: '1.0.0',
5 | buildDate: `${new Date().toISOString()}`,
6 | buildCommit: 'local',
7 | };
8 |
--------------------------------------------------------------------------------
/ndsweb/src/app/containers/monitor/monitor-container.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | }
4 |
5 | .error {
6 | padding: 10px;
7 |
8 | .mat-icon {
9 | vertical-align: bottom;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ndsweb/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 |
4 | buildVersion: '{{ BUILD_VERSION }}',
5 | buildDate: '{{ BUILD_DATE }}',
6 | buildCommit: '{{ BUILD_COMMIT }}'
7 | };
8 |
--------------------------------------------------------------------------------
/ndsweb/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 | @import 'themes';
3 |
4 | html, body { height: 100%; }
5 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
6 |
--------------------------------------------------------------------------------
/tests/ntest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Loop to repeatedly run ./tests
4 | while ./tests; do
5 | echo "Test succeeded, running again..."
6 | done
7 |
8 | # Exit the loop when ./tests fails
9 | echo "Test failed, exiting."
10 |
11 |
--------------------------------------------------------------------------------
/tests/ntest.sht:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Loop to repeatedly run ./tests
4 | while ./tests; do
5 | echo "Test succeeded, running again..."
6 | done
7 |
8 | # Exit the loop when ./tests fails
9 | echo "Test failed, exiting."
10 |
11 |
--------------------------------------------------------------------------------
/ndsweb/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "types": []
6 | },
7 | "files": ["src/main.ts"],
8 | "include": ["src/**/*.d.ts"],
9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/reorder-columns/reorder-columns.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (column of columns(); track column.value) {
3 |
4 | drag_handle
5 | {{ column.key }}
6 |
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/view-features/view-features.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ feature.friendlyName }}
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ndsweb/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "module": "commonjs",
6 | "target": "es2016",
7 | "types": ["jest", "node"]
8 | },
9 | "files": ["src/test-setup.ts"],
10 | "include": [
11 | "jest.config.ts",
12 | "src/**/*.test.ts",
13 | "src/**/*.spec.ts",
14 | "src/**/*.d.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "Build ndscpp",
6 | "type": "shell",
7 | "command": "make",
8 | "args": ["all"],
9 | "group": {
10 | "kind": "build",
11 | "isDefault": true
12 | },
13 | "problemMatcher": [],
14 | "detail": "Build the ndscpp program using make."
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/ndsweb/src/main.ts:
--------------------------------------------------------------------------------
1 | import { bootstrapApplication } from '@angular/platform-browser';
2 | import { appConfig } from './app/app.config';
3 | import { AppComponent } from './app/app.component';
4 | import { environment } from './environments/environment';
5 | import { enableProdMode } from '@angular/core';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | bootstrapApplication(AppComponent, appConfig).catch((err) =>
12 | console.error(err)
13 | );
14 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Your Platform",
5 | "includePath": [
6 | "${workspaceFolder}/**",
7 | "/usr/local/include",
8 | "/usr/local/include/nlohmann"
9 | ],
10 | "macFrameworkPath": [
11 | "/System/Library/Frameworks",
12 | "/Library/Frameworks"
13 | ],
14 | "intelliSenseMode": "macos-clang-x64",
15 | "compilerPath": "/usr/bin/clang"
16 | }
17 | ],
18 | "version": 4
19 | }
--------------------------------------------------------------------------------
/ndsweb/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | dist
5 | tmp
6 | out-tsc
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 |
37 | # System Files
38 | .DS_Store
39 | Thumbs.db
40 |
41 | .nx/cache
42 | .nx/workspace-data
43 |
44 | .angular
45 |
--------------------------------------------------------------------------------
/ndsweb/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | monitor-web
6 |
7 |
8 |
9 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Debug ndscpp",
6 | "type": "cppdbg",
7 | "request": "launch",
8 | "program": "${workspaceFolder}/ndscpp", // Path to your compiled binary
9 | "args": [], // Add program arguments here if needed
10 | "stopAtEntry": false,
11 | "cwd": "${workspaceFolder}",
12 | "environment": [],
13 | "externalConsole": false,
14 | "MIMode": "lldb",
15 | "preLaunchTask": "Build ndscpp", // Run the build task before debugging
16 | "setupCommands": [
17 | {
18 | "description": "Enable pretty-printing for gdb",
19 | "text": "-enable-pretty-printing",
20 | "ignoreFailures": true
21 | }
22 | ]
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/ndsweb/src/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ActivatedRouteSnapshot,
3 | Route,
4 | RouterStateSnapshot,
5 | } from '@angular/router';
6 |
7 | import { MonitorContainerComponent } from './containers';
8 | import { Store } from '@ngxs/store';
9 | import { MonitorActions } from './actions';
10 | import { inject } from '@angular/core';
11 |
12 | export const appRoutes: Route[] = [
13 | {
14 | path: '',
15 | component: MonitorContainerComponent,
16 | resolve: {
17 | data: (
18 | _route: ActivatedRouteSnapshot,
19 | _state: RouterStateSnapshot,
20 | store: Store = inject(Store)
21 | ) => {
22 | store.dispatch(new MonitorActions.LoadCanvases());
23 |
24 | },
25 | },
26 | },
27 | { path: '**', redirectTo: '' },
28 | ];
29 |
--------------------------------------------------------------------------------
/ndsweb/src/app/containers/monitor/monitor-container.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | NightDriver Web UI
4 |
5 |
6 |
14 |
15 | warning Connection error with server.
16 | {{ error.statusText }} ({{ error.status }})
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ndsweb/jest.config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | displayName: 'monitor-web',
3 | preset: './jest.preset.js',
4 | setupFilesAfterEnv: ['/src/test-setup.ts'],
5 | coverageDirectory: './coverage/monitor-web',
6 | transform: {
7 | '^.+\\.(ts|mjs|js|html)$': [
8 | 'jest-preset-angular',
9 | {
10 | tsconfig: '/tsconfig.spec.json',
11 | stringifyContentPathRegex: '\\.(html|svg)$',
12 | },
13 | ],
14 | },
15 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
16 | snapshotSerializers: [
17 | 'jest-preset-angular/build/serializers/no-ng-attributes',
18 | 'jest-preset-angular/build/serializers/ng-snapshot',
19 | 'jest-preset-angular/build/serializers/html-comment',
20 | ],
21 | testMatch: [
22 | '/src/**/__tests__/**/*.[jt]s?(x)',
23 | '/src/**/*(*.)@(spec|test).[jt]s?(x)',
24 | ],
25 | };
26 |
--------------------------------------------------------------------------------
/ndsweb/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { VERSION as ngVersion } from '@angular/common';
2 | import { Component } from '@angular/core';
3 | import { VERSION as ngMaterialVersion } from '@angular/material/core';
4 | import { RouterModule } from '@angular/router';
5 |
6 | import { environment } from 'src/environments/environment';
7 |
8 | @Component({
9 | imports: [RouterModule],
10 | selector: 'app-root',
11 | templateUrl: './app.component.html',
12 | styleUrl: './app.component.scss',
13 | })
14 | export class AppComponent {
15 | constructor() {
16 | console.log('@angular/core', ngVersion.full);
17 | console.log('@angular/material', ngMaterialVersion.full);
18 | console.log(
19 | `Build ${environment.buildVersion}-${environment.buildCommit}`
20 | );
21 | console.log(`Build Date`, new Date(environment.buildDate as string));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ndsweb/src/app/pipes/format-delta.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'formatDelta',
5 | })
6 | export class FormatDeltaPipe implements PipeTransform {
7 | transform(value: string | number, threshold = 5, width = 21): string {
8 | let time: number = value as number;
9 |
10 | if (typeof value === 'string') {
11 | time = parseFloat(value);
12 | }
13 |
14 | if (Math.abs(time) > 100) {
15 | return 'Unset';
16 | }
17 |
18 | if (width % 2 == 0) {
19 | width++;
20 | }
21 |
22 | // Normalize value to -1..1 range based on threshold
23 | const normalized = Math.min(1.0, Math.max(-1.0, time / threshold));
24 |
25 | const center = ~~(width / 2);
26 | const pos = ~~(center + normalized * center);
27 |
28 | let meter = '';
29 | for (let i = 0; i < width; i++) {
30 | meter += i == pos ? '|' : '-';
31 | }
32 | return `${time.toFixed(1)}s ${meter}`;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ndsweb/src/app/pipes/format-size.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | const BYTES_IN_GIGABYTE = 1073741824;
4 | const BYTES_IN_MEGABYTE = 1048576;
5 | const BYTES_IN_KILOBYTE = 1024;
6 |
7 | @Pipe({
8 | name: 'formatSize',
9 | })
10 | export class FormatSizePipe implements PipeTransform {
11 | transform(value: string | number): string {
12 | let bytes: number = value as number;
13 |
14 | if (typeof value === 'string') {
15 | bytes = parseInt(value);
16 | }
17 |
18 | const gigabytes = bytes / BYTES_IN_GIGABYTE;
19 | const megabytes = bytes / BYTES_IN_MEGABYTE;
20 | const kilobytes = bytes / BYTES_IN_KILOBYTE;
21 |
22 | if (gigabytes > 1) {
23 | return `${gigabytes.toFixed(2)} GB`;
24 | }
25 |
26 | if (megabytes > 1) {
27 | return `${megabytes.toFixed(2)} MB`;
28 | }
29 |
30 | if (kilobytes > 1) {
31 | return `${kilobytes.toFixed(2)} KB`;
32 | }
33 |
34 | return `${bytes} B`;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ndsweb/eslint.config.js:
--------------------------------------------------------------------------------
1 | const nx = require('@nx/eslint-plugin');
2 |
3 | module.exports = [
4 | ...nx.configs['flat/base'],
5 | ...nx.configs['flat/typescript'],
6 | ...nx.configs['flat/javascript'],
7 | {
8 | ignores: ['**/dist'],
9 | },
10 | {
11 | files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
12 | // Override or add rules here
13 | rules: {},
14 | },
15 | ...nx.configs['flat/angular'],
16 | ...nx.configs['flat/angular-template'],
17 | {
18 | files: ['**/*.ts'],
19 | rules: {
20 | '@angular-eslint/directive-selector': [
21 | 'error',
22 | {
23 | type: 'attribute',
24 | prefix: 'app',
25 | style: 'camelCase',
26 | },
27 | ],
28 | '@angular-eslint/component-selector': [
29 | 'error',
30 | {
31 | type: 'element',
32 | prefix: 'app',
33 | style: 'kebab-case',
34 | },
35 | ],
36 | },
37 | },
38 | {
39 | files: ['**/*.html'],
40 | // Override or add rules here
41 | rules: {},
42 | },
43 | ];
44 |
--------------------------------------------------------------------------------
/monitor/Makefile:
--------------------------------------------------------------------------------
1 | # Compiler settings
2 | CXX = g++
3 | CXXFLAGS = -std=c++20 -Wall -Wextra -Werror -O2
4 | INCLUDES = -I.
5 | LDFLAGS =
6 |
7 | # Libraries needed
8 | LIBS = -lcurl -lfmt -lncursesw
9 |
10 | # Binary name
11 | TARGET = ledmon
12 |
13 | # Source files
14 | SOURCES = main.cpp content.cpp
15 |
16 | # Object files
17 | OBJECTS = $(SOURCES:.cpp=.o)
18 |
19 | # Detect platform
20 | UNAME_S := $(shell uname -s)
21 | ifeq ($(UNAME_S), Darwin)
22 | INCLUDES += -I$(shell brew --prefix)/include/ -I$(shell brew --prefix ncurses)/include/
23 | LDFLAGS += -L$(shell brew --prefix)/lib/ -L$(shell brew --prefix ncurses)/lib/
24 | endif
25 |
26 | # Default target
27 | all: $(TARGET)
28 |
29 | # Link the target binary
30 | $(TARGET): $(OBJECTS)
31 | @echo "Linking $@..."
32 | @$(CXX) $(LDFLAGS) $(OBJECTS) -o $(TARGET) $(LIBS)
33 |
34 | # Compile source files
35 | %.o: %.cpp
36 | @echo "Compiling $<..."
37 | @$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
38 |
39 | # Clean build files
40 | clean:
41 | @echo "Cleaning build files..."
42 | @rm -f $(OBJECTS) $(TARGET)
43 |
44 | .PHONY: all clean
45 |
--------------------------------------------------------------------------------
/ledeffectbase.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | using namespace std;
3 |
4 | // LEDEffectBase
5 | //
6 | // A helper class that implements the ILEDEffect interface.
7 |
8 | #include "interfaces.h"
9 | #include "schedule.h"
10 |
11 | class LEDEffectBase : public ILEDEffect
12 | {
13 | protected:
14 | string _name;
15 | shared_ptr _ptrSchedule = nullptr;
16 |
17 | public:
18 | LEDEffectBase(const string& name) : _name(name) {}
19 |
20 | virtual ~LEDEffectBase() = default;
21 |
22 | const string& Name() const override { return _name; }
23 |
24 | // Default implementation for Start does nothing
25 | void Start(ICanvas& canvas) override
26 | {
27 | }
28 |
29 | // Default implementation for Update does nothing
30 | void Update(ICanvas& canvas, milliseconds deltaTime) override
31 | {
32 | }
33 |
34 | void SetSchedule(const shared_ptr schedule) override
35 | {
36 | _ptrSchedule = schedule;
37 | }
38 |
39 | const shared_ptr GetSchedule() const override
40 | {
41 | return _ptrSchedule;
42 | }
43 | };
44 |
45 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/reorder-columns/reorder-columns.component.ts:
--------------------------------------------------------------------------------
1 | import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
2 | import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';
3 | import { MatIcon } from '@angular/material/icon';
4 | import { MatList, MatListItem, MatListItemIcon } from '@angular/material/list';
5 |
6 | import { Column } from '../../models';
7 |
8 | @Component({
9 | selector: 'app-reorder-columns',
10 | templateUrl: './reorder-columns.component.html',
11 | styleUrls: ['./reorder-columns.component.scss'],
12 | changeDetection: ChangeDetectionStrategy.OnPush,
13 | standalone: true,
14 | imports: [
15 | MatList,
16 | MatListItem,
17 | MatListItemIcon,
18 | MatIcon,
19 | CdkDrag,
20 | CdkDragHandle,
21 | CdkDropList
22 | ]
23 | })
24 | export class ReorderColumnsComponent {
25 |
26 | columns = input();
27 | columnsChange = output();
28 |
29 | drop(event: CdkDragDrop) {
30 | const columns = this.columns() as Column[];
31 | moveItemInArray(columns, event.previousIndex, event.currentIndex);
32 | this.columnsChange.emit(columns);
33 | }
34 | }
--------------------------------------------------------------------------------
/tests/Makefile:
--------------------------------------------------------------------------------
1 | # Compiler settings
2 | CXX = clang++
3 | CXXFLAGS = -std=c++20 -Wall -Wextra -Werror -O2
4 | INCLUDES = -I.
5 | LDFLAGS =
6 |
7 | # Libraries needed
8 | LIBS = -lpthread -lcurl -lcpr -lgtest_main -lgtest
9 |
10 | # Binary name
11 | TARGET = tests
12 |
13 | # Source files
14 | SOURCES = tests.cpp
15 |
16 | # Object files
17 | OBJECTS = $(SOURCES:.cpp=.o)
18 |
19 | # Detect platform
20 | UNAME_S := $(shell uname -s)
21 | ifeq ($(UNAME_S), Darwin)
22 | # macOS-specific settings using Homebrew
23 | INCLUDES += -I$(shell brew --prefix)/include/
24 | LDFLAGS += -L$(shell brew --prefix)/lib/
25 | endif
26 |
27 | # Default target
28 | all: $(TARGET)
29 |
30 | # Link the target binary
31 | $(TARGET): $(OBJECTS)
32 | @echo "Linking $@..."
33 | @$(CXX) $(LDFLAGS) $(LIBS) -o $(TARGET) $(OBJECTS)
34 |
35 | # Compile source files
36 | %.o: %.cpp
37 | @echo "Compiling $<..."
38 | @$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
39 |
40 | # Clean build files
41 | clean:
42 | @echo "Cleaning build files..."
43 | @rm -f $(OBJECTS) $(TARGET)
44 |
45 | # Run the tests
46 | test: $(TARGET)
47 | @echo "Running tests..."
48 | @./$(TARGET)
49 |
50 | # Install dependencies on macOS
51 | install-deps-mac:
52 | @echo "Installing dependencies via Homebrew..."
53 | @brew install googletest cpr
54 |
55 | .PHONY: all clean test install-deps-mac
--------------------------------------------------------------------------------
/ndsweb/src/app/app.config.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { provideHttpClient } from '@angular/common/http';
3 | import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
4 | import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
5 | import { provideRouter } from '@angular/router';
6 |
7 | import { provideStore } from '@ngxs/store';
8 |
9 | import { appRoutes } from './app.routes';
10 | import { MonitorService } from './services';
11 | import { MonitorState } from './state';
12 | import { APP_SERVER_URL } from './tokens';
13 | import { provideToastr } from 'ngx-toastr';
14 |
15 | export const appConfig: ApplicationConfig = {
16 | providers: [
17 | CommonModule,
18 | provideHttpClient(),
19 | provideAnimationsAsync(),
20 | provideZoneChangeDetection({ eventCoalescing: true }),
21 | provideToastr({
22 | countDuplicates: true,
23 | preventDuplicates: true,
24 | resetTimeoutOnDuplicate: true,
25 | maxOpened: 5,
26 | }),
27 | provideRouter(appRoutes),
28 | provideStore([MonitorState], {
29 | developmentMode: true,
30 | }),
31 |
32 | MonitorService,
33 |
34 | { provide: APP_SERVER_URL, useValue: 'http://localhost:7777/api' },
35 | ],
36 | };
37 |
--------------------------------------------------------------------------------
/ndsweb/src/app/components/view-features/view-features.component.ts:
--------------------------------------------------------------------------------
1 | import { NgFor } from '@angular/common';
2 | import {
3 | ChangeDetectionStrategy,
4 | Component,
5 | input,
6 | output,
7 | } from '@angular/core';
8 | import { MatIconButton } from '@angular/material/button';
9 | import { MatIcon } from '@angular/material/icon';
10 | import {
11 | MatList,
12 | MatListItem,
13 | MatListItemMeta,
14 | MatListItemTitle,
15 | } from '@angular/material/list';
16 |
17 | import { Canvas, Feature } from 'src/app/services';
18 |
19 | @Component({
20 | selector: 'app-view-features',
21 | templateUrl: `./view-features.component.html`,
22 | styleUrl: `./view-features.component.scss`,
23 | changeDetection: ChangeDetectionStrategy.OnPush,
24 | standalone: true,
25 | imports: [
26 | MatList,
27 | MatListItem,
28 | NgFor,
29 | MatIcon,
30 | MatIconButton,
31 | MatListItemMeta,
32 | MatListItemTitle,
33 | ],
34 | })
35 | export class ViewFeaturesComponent {
36 | get features() {
37 | return this.canvas()?.features;
38 | }
39 |
40 | canvas = input