Ready to test in Fab
This commit is contained in:
parent
1f5deedc73
commit
2c38ecb399
30
.kanbn/index.md
Normal file
30
.kanbn/index.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
startedColumns:
|
||||||
|
- 'In Progress'
|
||||||
|
completedColumns:
|
||||||
|
- Done
|
||||||
|
---
|
||||||
|
|
||||||
|
# Barcode-Host
|
||||||
|
|
||||||
|
## Backlog
|
||||||
|
|
||||||
|
- [update-os](tasks/update-os.md)
|
||||||
|
- [apt-get-install](tasks/apt-get-install.md)
|
||||||
|
- [configure-ufw](tasks/configure-ufw.md)
|
||||||
|
- [install-ubuntu-frame](tasks/install-ubuntu-frame.md)
|
||||||
|
- [netplan](tasks/netplan.md)
|
||||||
|
- [install-net-7-0](tasks/install-net-7-0.md)
|
||||||
|
- [pull-repo](tasks/pull-repo.md)
|
||||||
|
- [run-secrets-task](tasks/run-secrets-task.md)
|
||||||
|
- [install-vscode-extensions](tasks/install-vscode-extensions.md)
|
||||||
|
- [run-test-ports](tasks/run-test-ports.md)
|
||||||
|
- [publish](tasks/publish.md)
|
||||||
|
- [create-as-service](tasks/create-as-service.md)
|
||||||
|
- [setup-nginx](tasks/setup-nginx.md)
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
|
||||||
|
## In Progress
|
||||||
|
|
||||||
|
## Done
|
13
.kanbn/tasks/apt-get-install.md
Normal file
13
.kanbn/tasks/apt-get-install.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# apt-get-install
|
||||||
|
|
||||||
|
sudo -i
|
||||||
|
apt-get install links unzip net-tools ufw nginx git -y
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
72
.kanbn/tasks/configure-ufw.md
Normal file
72
.kanbn/tasks/configure-ufw.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# configure-ufw
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 22 comment "01) SSH"
|
||||||
|
ufw allow to 0.0.0.0/0 port 80 comment "02) HTTP"
|
||||||
|
ufw allow to 0.0.0.0/0 port 443 comment "03) HTTPS"
|
||||||
|
ufw allow to 0.0.0.0/0 port 9418 comment "04) Git"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8005 comment "05) Pi-hole"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8006 comment "06) Ajenti"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8007 comment "07) code-server"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8008 comment "08) Nginx"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 5002 comment "09) BaGet"
|
||||||
|
ufw allow to 0.0.0.0/0 port 5000 comment "10) .netCore"
|
||||||
|
ufw allow to 0.0.0.0/0 port 5001 comment "11) .netCore"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 53 comment "12) DNS"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 67 comment "13) Unknown"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 9654 comment "14) barcode-server"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8009 comment "15) barcode-server-statistics"
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 9400 comment "16) dashkiosk"
|
||||||
|
ufw delete 16
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 8010 comment "16) Test"
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 5052 comment "17) NGINdeX.io"
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 3000 comment "18) gogs"
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 4001 comment "19) gogs"
|
||||||
|
ufw delete 19
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 4001 comment "19) photoview api"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 1234 comment "20) photoview ui"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 3306 comment "21) mysql"
|
||||||
|
ufw allow from 192.168.0.0/24 to any port 8011 comment "22) syncthing"
|
||||||
|
ufw allow from 0.0.0.0/0 to any port 5201 comment "23) iperf3"
|
||||||
|
ufw enable
|
||||||
|
ufw status numbered
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
Status: active
|
||||||
|
|
||||||
|
To Action From
|
||||||
|
-- ------ ----
|
||||||
|
[ 1] 22 ALLOW IN 192.168.0.0/24 # 01) SSH
|
||||||
|
[ 2] 80 ALLOW IN Anywhere # 02) HTTP
|
||||||
|
[ 3] 443 ALLOW IN Anywhere # 03) HTTPS
|
||||||
|
[ 4] 9418 ALLOW IN Anywhere # 04) Git
|
||||||
|
[ 5] 8005 ALLOW IN 192.168.0.0/24 # 05) Pi-hole
|
||||||
|
[ 6] 8006 ALLOW IN 192.168.0.0/24 # 06) Ajenti
|
||||||
|
[ 7] 8007 ALLOW IN 192.168.0.0/24 # 07) code-server
|
||||||
|
[ 8] 8008 ALLOW IN 192.168.0.0/24 # 08) Nginx
|
||||||
|
[ 9] 5002 ALLOW IN 192.168.0.0/24 # 09) BaGet
|
||||||
|
[10] 5000 ALLOW IN Anywhere # 10) .netCore
|
||||||
|
[11] 5001 ALLOW IN Anywhere # 11) .netCore
|
||||||
|
[12] 53 ALLOW IN 192.168.0.0/24 # 12) DNS
|
||||||
|
[13] 67 ALLOW IN 192.168.0.0/24 # 13) Unknown
|
||||||
|
[14] 9654 ALLOW IN 192.168.0.0/24 # 14) barcode-server
|
||||||
|
[15] 8009 ALLOW IN 192.168.0.0/24 # 15) barcode-server-statistics
|
||||||
|
[16] 8010 ALLOW IN Anywhere # 16) Test
|
||||||
|
[17] 5052 ALLOW IN Anywhere # 17) NGINdeX.io
|
||||||
|
[18] 3000 ALLOW IN Anywhere # 18) gogs
|
||||||
|
[19] 4001 ALLOW IN 192.168.0.0/24 # 19) photoview api
|
||||||
|
[20] 1234 ALLOW IN 192.168.0.0/24 # 20) photoview ui
|
||||||
|
[21] 3306 ALLOW IN 192.168.0.0/24 # 21) mysql
|
||||||
|
[22] 8011 ALLOW IN 192.168.0.0/24 # 22) syncthing
|
||||||
|
[23] 5201 ALLOW IN Anywhere # 23) iperf3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
40
.kanbn/tasks/create-as-service.md
Normal file
40
.kanbn/tasks/create-as-service.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create as Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
echo >/etc/systemd/system/barcode-host.service && nano /etc/systemd/system/barcode-host.service
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
[Unit]
|
||||||
|
Description=Barcode Server
|
||||||
|
After=multi-user.target
|
||||||
|
[Service]
|
||||||
|
User=unity4
|
||||||
|
WorkingDirectory=/var/www/Barcode-Host/Server
|
||||||
|
ExecStart=/usr/local/bin/dotnet /var/www/Barcode-Host/Server/Barcode.Host.Server.dll
|
||||||
|
Restart=always
|
||||||
|
# Environment=ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
# Environment=ASPNETCORE_ENVIRONMENT=Staging
|
||||||
|
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable barcode-host.service
|
||||||
|
systemctl start barcode-host.service
|
||||||
|
systemctl status barcode-host.service
|
||||||
|
systemctl stop barcode-host.service
|
||||||
|
journalctl -fu barcode-host.service
|
||||||
|
journalctl --rotate
|
||||||
|
journalctl --vacuum-time=1s
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [ ] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
22
.kanbn/tasks/install-net-7-0.md
Normal file
22
.kanbn/tasks/install-net-7-0.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# Install .net 7.0
|
||||||
|
|
||||||
|
```bask
|
||||||
|
# https://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#scripted-install
|
||||||
|
cd /home/unity4
|
||||||
|
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
|
||||||
|
chmod +x ./dotnet-install.sh
|
||||||
|
./dotnet-install.sh --channel 7.0
|
||||||
|
export DOTNET_ROOT=$HOME/.dotnet
|
||||||
|
export PATH=$PATH:$HOME/.dotnet:$HOME/.dotnet/tools
|
||||||
|
ln -s /home/unity4/.dotnet/dotnet /usr/local/bin/dotnet
|
||||||
|
dotnet --info
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
24
.kanbn/tasks/install-ubuntu-frame.md
Normal file
24
.kanbn/tasks/install-ubuntu-frame.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# install-ubuntu-frame
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get install links unzip net-tools -y
|
||||||
|
snap install dashkiosk
|
||||||
|
timedatectl set-timezone America/Phoenix
|
||||||
|
snap restart dashkiosk
|
||||||
|
snap install ubuntu-frame wpe-webkit-mir-kiosk
|
||||||
|
snap set wpe-webkit-mir-kiosk daemon=true
|
||||||
|
snap set wpe-webkit-mir-kiosk url=http://localhost:9400/receiver
|
||||||
|
wpe-webkit-mir-kiosk.cog http://localhost:9400/receiver
|
||||||
|
/snap/wpe-webkit-mir-kiosk/current/bin/setup.sh
|
||||||
|
wpe-webkit-mir-kiosk.cog http://localhost:9400/receiver
|
||||||
|
snap set ubuntu-frame daemon=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [ ] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
15
.kanbn/tasks/install-vscode-extensions.md
Normal file
15
.kanbn/tasks/install-vscode-extensions.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# install-vscode-extensions
|
||||||
|
|
||||||
|
- .NET Watch Attach (trottero.dotnetwatchattach)
|
||||||
|
- C# (ms-dotnettools.csharp)
|
||||||
|
- Git Graph (mhutchie.git-graph)
|
||||||
|
- Live Preview (ms-vscode.live-server)
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
60
.kanbn/tasks/netplan.md
Normal file
60
.kanbn/tasks/netplan.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# netplan
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip link
|
||||||
|
```
|
||||||
|
```echo
|
||||||
|
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
|
||||||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||||
|
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 10
|
||||||
|
link/ether 6c:0b:84:e3:94:11 brd ff:ff:ff:ff:ff:ff
|
||||||
|
altname enp0s31f6
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
https://ubuntu.com/server/docs/network-configuration
|
||||||
|
ip a
|
||||||
|
ip address show eno1
|
||||||
|
echo >/etc/netplan/99_config.yaml && nano /etc/netplan/99_config.yaml
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
network:
|
||||||
|
version: 2
|
||||||
|
renderer: networkd
|
||||||
|
ethernets:
|
||||||
|
eno1:
|
||||||
|
addresses:
|
||||||
|
- 192.168.0.204/24
|
||||||
|
routes:
|
||||||
|
- to: default
|
||||||
|
via: 192.168.0.1
|
||||||
|
nameservers:
|
||||||
|
addresses: [192.168.0.1, 8.8.8.8, 4.4.4.4]
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
netplan apply
|
||||||
|
ip addr flush eno1
|
||||||
|
# soft reset
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
network:
|
||||||
|
version: 2
|
||||||
|
renderer: networkd
|
||||||
|
ethernets:
|
||||||
|
eno1:
|
||||||
|
addresses:
|
||||||
|
- 10.95.154.54/24
|
||||||
|
routes:
|
||||||
|
- to: default
|
||||||
|
via: 10.95.154.1
|
||||||
|
nameservers:
|
||||||
|
addresses: [10.95.128.11, 10.64.152.171, 8.8.8.8, 4.4.4.4]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [ ] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
35
.kanbn/tasks/publish.md
Normal file
35
.kanbn/tasks/publish.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# publish
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
systemctl stop barcode-host.service
|
||||||
|
rm -r /var/www/Barcode-Host/Server
|
||||||
|
mkdir /var/www
|
||||||
|
mkdir /var/www/Barcode-Host
|
||||||
|
mkdir /var/www/Barcode-Host/Server
|
||||||
|
cd /home/unity4/Barcode-Host/Server
|
||||||
|
dotnet publish --configuration Release --output /var/www/Barcode-Host/Server
|
||||||
|
cd /var/www/Barcode-Host/Server
|
||||||
|
dotnet /var/www/Barcode-Host/Server/Barcode.Host.Server.dll
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
2023-06-03 16:02:25.011 -07:00 [Information] (Barcode.Host.Server.Program.) () () Starting Web Application
|
||||||
|
2023-06-03 16:02:25.062 -07:00 [Information] (Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.) () () User profile is available. Using '"/root/.aspnet/DataProtection-Keys"' as key repository; keys will not be encrypted at rest.
|
||||||
|
2023-06-03 16:02:25.093 -07:00 [Information] (Barcode.Host.Server.HostedService.TimedHostedService.StartAsync) () () Timed Hosted Service: 1234567:3070 running.
|
||||||
|
2023-06-03 16:02:25.175 -07:00 [Information] (Microsoft.Hosting.Lifetime.) () () Now listening on: "http://localhost:5003"
|
||||||
|
2023-06-03 16:02:25.175 -07:00 [Information] (Microsoft.Hosting.Lifetime.) () () Application started. Press Ctrl+C to shut down.
|
||||||
|
2023-06-03 16:02:25.176 -07:00 [Information] (Microsoft.Hosting.Lifetime.) () () Hosting environment: "Production"
|
||||||
|
2023-06-03 16:02:25.176 -07:00 [Information] (Microsoft.Hosting.Lifetime.) () () Content root path: "/var/www/Barcode-Host/Server"
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
links http://localhost:5003/api/lastScan
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [ ] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
17
.kanbn/tasks/pull-repo.md
Normal file
17
.kanbn/tasks/pull-repo.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# Pull Repo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/unity4
|
||||||
|
git clone http://76df8eca4a6c11fe29a58c3be37543c11389ab93@192.168.0.73:3000/mikepharesjr/Barcode-Host.git
|
||||||
|
cd Barcode-Host
|
||||||
|
code .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
15
.kanbn/tasks/run-secrets-task.md
Normal file
15
.kanbn/tasks/run-secrets-task.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# run-secrets-task
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd Server
|
||||||
|
dotnet user-secrets set RootPassword 4hink
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
22
.kanbn/tasks/run-test-ports.md
Normal file
22
.kanbn/tasks/run-test-ports.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# run-test-ports
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -l /dev/ttyUSB*
|
||||||
|
```
|
||||||
|
```echo
|
||||||
|
# crw-rw---- 1 root dialout 188, 0 Jun 3 14:54 /dev/ttyUSB0
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
adduser unity4 dialout
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
113
.kanbn/tasks/setup-nginx.md
Normal file
113
.kanbn/tasks/setup-nginx.md
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# setup-nginx
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo >/etc/nginx/sites-available/default && nano /etc/nginx/sites-available/default
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.html index.htm index.nginx-debian.html;
|
||||||
|
server_name _;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
systemctl restart nginx
|
||||||
|
lsof -i -P -n | grep LISTEN
|
||||||
|
links http://192.168.0.204/
|
||||||
|
nginx -t
|
||||||
|
nginx -s reload
|
||||||
|
echo >/etc/nginx/sites-available/Barcode-Host-Server && nano /etc/nginx/sites-available/Barcode-Host-Server
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.html index.htm index.nginx-debian.html;
|
||||||
|
server_name _;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
echo >/home/unity4/localhost.conf && nano /home/unity4/localhost.conf
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
[req]
|
||||||
|
default_bits = 2048
|
||||||
|
default_keyfile = localhost.key
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
req_extensions = req_ext
|
||||||
|
x509_extensions = v3_ca
|
||||||
|
|
||||||
|
[req_distinguished_name]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = US
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Arizona
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Mesa
|
||||||
|
organizationName = Organization Name (eg, company)
|
||||||
|
organizationName_default = Infineon Technologies Americas Corp.
|
||||||
|
organizationalUnitName = organizationalunit
|
||||||
|
organizationalUnitName_default = Development
|
||||||
|
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||||
|
commonName_default = unity4
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
[req_ext]
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[v3_ca]
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[alt_names]
|
||||||
|
DNS.1 = unity4
|
||||||
|
DNS.2 = localhost
|
||||||
|
DNS.3 = 127.0.0.1
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/localhost.key -out /etc/nginx/localhost.crt -config /home/unity4/localhost.conf
|
||||||
|
ls /etc/nginx
|
||||||
|
echo >/etc/nginx/sites-available/Barcode-Host-Server && nano /etc/nginx/sites-available/Barcode-Host-Server
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
server {
|
||||||
|
server_name _;
|
||||||
|
ssl_certificate 'localhost.crt';
|
||||||
|
listen 443 default_server ssl http2;
|
||||||
|
ssl_certificate_key 'localhost.key';
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
listen [::]:443 default_server ssl http2;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:5003;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
ln -s /etc/nginx/sites-available/Barcode-Host-Server /etc/nginx/sites-enabled/Barcode-Host-Server
|
||||||
|
nginx -t
|
||||||
|
nginx -s reload
|
||||||
|
links https://localhost/api/lastscan
|
||||||
|
links https://unity4/api/lastscan
|
||||||
|
```
|
||||||
|
```conf
|
||||||
|
# C:\Windows\System32\drivers\etc\hosts
|
||||||
|
192.168.0.204 unity4
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
17
.kanbn/tasks/update-os.md
Normal file
17
.kanbn/tasks/update-os.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
# update-os
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update
|
||||||
|
apt upgrade -y
|
||||||
|
apt install update-manager-core
|
||||||
|
do-release-upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [x] phares3757
|
||||||
|
- [x] unity4
|
||||||
|
- [x] unity5
|
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@ -1,9 +1,12 @@
|
|||||||
{
|
{
|
||||||
"cSpell.enabled": false,
|
"cSpell.enabled": false,
|
||||||
"files.exclude": {
|
|
||||||
"**/.git": false
|
|
||||||
},
|
|
||||||
"thunder-client.saveToWorkspace": true,
|
"thunder-client.saveToWorkspace": true,
|
||||||
"thunder-client.workspaceRelativePath": ".vscode",
|
"thunder-client.workspaceRelativePath": ".vscode",
|
||||||
"coverage-gutters.coverageBaseDir": "../.vscode/TestResults/*"
|
"coverage-gutters.coverageBaseDir": "../.vscode/TestResults/*",
|
||||||
|
"[markdown]": {
|
||||||
|
"editor.wordWrap": "off"
|
||||||
|
},
|
||||||
|
"files.exclude": {
|
||||||
|
"**/.git": false
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VSTestLogger>trx</VSTestLogger>
|
<VSTestLogger>trx</VSTestLogger>
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
namespace Server.Tests;
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
78
Server.Tests/UnitTestLastScanController.cs
Normal file
78
Server.Tests/UnitTestLastScanController.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using Barcode.Host.Shared.DataModels;
|
||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class UnitTestLastScanController
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma warning disable CS8618
|
||||||
|
|
||||||
|
private static ILogger _Logger;
|
||||||
|
private static string _ControllerName;
|
||||||
|
private static TestContext _TestContext;
|
||||||
|
private static WebApplicationFactory<Server.Program> _WebApplicationFactory;
|
||||||
|
|
||||||
|
#pragma warning restore
|
||||||
|
|
||||||
|
[ClassInitialize]
|
||||||
|
public static void ClassInitAsync(TestContext testContext)
|
||||||
|
{
|
||||||
|
_TestContext = testContext;
|
||||||
|
_Logger = Log.ForContext<UnitTestLastScanController>();
|
||||||
|
_WebApplicationFactory = new WebApplicationFactory<Server.Program>();
|
||||||
|
_ControllerName = nameof(Server.ApiControllers.LastScanController)[..^10];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void NonThrowTryCatch()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{ throw new Exception(); }
|
||||||
|
catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestControllerName()
|
||||||
|
{
|
||||||
|
_Logger.Information("Starting Web Application");
|
||||||
|
Assert.AreEqual(ILastScanController<string>.GetRouteName(), _ControllerName);
|
||||||
|
_Logger.Information($"{_TestContext?.TestName} completed");
|
||||||
|
NonThrowTryCatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
[Ignore]
|
||||||
|
#endif
|
||||||
|
[TestMethod]
|
||||||
|
public void GetScan()
|
||||||
|
{
|
||||||
|
_Logger.Information("Starting Web Application");
|
||||||
|
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
|
||||||
|
ILastScanService lastScanService = serviceProvider.GetRequiredService<ILastScanService>();
|
||||||
|
Result<string> result = lastScanService.GetScan();
|
||||||
|
Assert.IsNotNull(result?.Results);
|
||||||
|
_Logger.Information($"{_TestContext?.TestName} completed");
|
||||||
|
NonThrowTryCatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
[Ignore]
|
||||||
|
#endif
|
||||||
|
[TestMethod]
|
||||||
|
public async Task GetScanApi()
|
||||||
|
{
|
||||||
|
HttpClient httpClient = _WebApplicationFactory.CreateClient();
|
||||||
|
_Logger.Information("Starting Web Application");
|
||||||
|
string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/O171927.1.37/");
|
||||||
|
File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{_ControllerName}-{nameof(GetScan)}.json"), json);
|
||||||
|
Result<string>? result = System.Text.Json.JsonSerializer.Deserialize<Result<string>>(json);
|
||||||
|
Assert.IsNotNull(result?.Results);
|
||||||
|
_Logger.Information($"{_TestContext?.TestName} completed");
|
||||||
|
NonThrowTryCatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
Server.Tests/Usings.cs
Normal file
1
Server.Tests/Usings.cs
Normal file
@ -0,0 +1 @@
|
|||||||
|
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
20
Server/ApiControllers/LastScanController.cs
Normal file
20
Server/ApiControllers/LastScanController.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Server.ApiControllers;
|
||||||
|
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class LastScanController : Controller, ILastScanController<IActionResult>
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ILastScanService _LastScanService;
|
||||||
|
|
||||||
|
public LastScanController(ILastScanService lastScanService) =>
|
||||||
|
_LastScanService = lastScanService;
|
||||||
|
|
||||||
|
[HttpGet()]
|
||||||
|
public IActionResult GetScan() =>
|
||||||
|
Json(_LastScanService.GetScan(), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<UserSecretsId>02dce973-df1d-4325-962a-ed549af8d4c5</UserSecretsId>
|
<UserSecretsId>02dce973-df1d-4325-962a-ed549af8d4c5</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -22,6 +22,7 @@
|
|||||||
<DefineConstants>Linux</DefineConstants>
|
<DefineConstants>Linux</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CliWrap" Version="3.6.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||||
@ -31,9 +32,18 @@
|
|||||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||||
|
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Shared\Barcode.Host.Shared.csproj" />
|
<ProjectReference Include="..\Shared\Barcode.Host.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Include="appsettings.Development.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
186
Server/HostedService/TimedHostedService.cs
Normal file
186
Server/HostedService/TimedHostedService.cs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
using Barcode.Host.Server.Models;
|
||||||
|
using Barcode.Host.Shared.DataModels;
|
||||||
|
using Barcode.Host.Shared.KeyboardMouse;
|
||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Serilog.Context;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Server.HostedService;
|
||||||
|
|
||||||
|
public class TimedHostedService : IHostedService, IAggregateInputReader, IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
public event InputReader.RaiseKeyPress? OnKeyPress;
|
||||||
|
|
||||||
|
private readonly int _ExecutionCount;
|
||||||
|
private readonly AppSettings _AppSettings;
|
||||||
|
private readonly ISerialService _SerialService;
|
||||||
|
private readonly ILastScanService _LastScanService;
|
||||||
|
private readonly ILogger<TimedHostedService> _Logger;
|
||||||
|
private readonly ILinuxGroupManager _LinuxGroupManager;
|
||||||
|
private readonly Dictionary<string, InputReader> _Readers;
|
||||||
|
private readonly Dictionary<EventCode, char> _CharToEventCodes;
|
||||||
|
private readonly List<(string MethodName, Timer Timer)> _Timers;
|
||||||
|
|
||||||
|
public TimedHostedService(ILogger<TimedHostedService> logger, AppSettings appSettings, ILinuxGroupManager linuxGroupManager, ILastScanService lastScanService, ISerialService serialService)
|
||||||
|
{
|
||||||
|
_Readers = new();
|
||||||
|
_Logger = logger;
|
||||||
|
_ExecutionCount = 0;
|
||||||
|
_CharToEventCodes = new();
|
||||||
|
_AppSettings = appSettings;
|
||||||
|
_SerialService = serialService;
|
||||||
|
_LastScanService = lastScanService;
|
||||||
|
_LinuxGroupManager = linuxGroupManager;
|
||||||
|
Timer writeTimer = new(Write, null, Timeout.Infinite, Timeout.Infinite);
|
||||||
|
Timer scanForNewInputsTimer = new(ScanForNewInputs, null, Timeout.Infinite, Timeout.Infinite);
|
||||||
|
_Timers = new List<(string, Timer)>() { (nameof(Write), writeTimer), (nameof(ScanForNewInputs), scanForNewInputsTimer) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
string? methodName = IMethodName.GetActualAsyncMethodName();
|
||||||
|
using (LogContext.PushProperty("MethodName", methodName))
|
||||||
|
{
|
||||||
|
_Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} running.");
|
||||||
|
_SerialService.Open();
|
||||||
|
if (!_LinuxGroupManager.IsInInputGroup().WaitAsync(stoppingToken).Result)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_AppSettings.RootPassword))
|
||||||
|
throw new Exception($"Please check appsettings file(s) for <{nameof(_AppSettings.RootPassword)}>!");
|
||||||
|
_ = _LinuxGroupManager.AddUserToInputGroup(_AppSettings.RootPassword);
|
||||||
|
_ = _LinuxGroupManager.RebootSystem(_AppSettings.RootPassword);
|
||||||
|
}
|
||||||
|
List<(EventCode, char)> collection = _LastScanService.IncludeEventCodes();
|
||||||
|
foreach ((EventCode eventCode, char @char) in collection)
|
||||||
|
_CharToEventCodes.Add(eventCode, @char);
|
||||||
|
int dueTime = 0;
|
||||||
|
foreach ((string _, Timer timer) in _Timers)
|
||||||
|
{
|
||||||
|
dueTime += 300;
|
||||||
|
_ = timer.Change(dueTime, Timeout.Infinite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
string? methodName = IMethodName.GetActualAsyncMethodName();
|
||||||
|
using (LogContext.PushProperty("MethodName", methodName))
|
||||||
|
{
|
||||||
|
_Logger.LogInformation($"Timed Hosted Service: {_AppSettings.GitCommitSeven}:{Environment.ProcessId} is stopping.");
|
||||||
|
for (short i = 0; i < short.MaxValue; i++)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
if (_ExecutionCount == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach ((string _, Timer timer) in _Timers)
|
||||||
|
timer.Dispose();
|
||||||
|
foreach (InputReader inputReader in _Readers.Values)
|
||||||
|
{
|
||||||
|
inputReader.OnKeyPress -= ReaderOnOnKeyPress;
|
||||||
|
inputReader.Dispose();
|
||||||
|
}
|
||||||
|
_Readers.Clear();
|
||||||
|
_SerialService.Close();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReaderOnOnKeyPress(KeyPressEvent e)
|
||||||
|
{
|
||||||
|
OnKeyPress?.Invoke(e);
|
||||||
|
if (e.TimeSpan.TotalMilliseconds > _AppSettings.ClearLastScanServiceAfter)
|
||||||
|
_LastScanService.Clear();
|
||||||
|
if (e.KeyState == KeyState.KeyUp && _CharToEventCodes.TryGetValue(e.EventCode, out char @char))
|
||||||
|
_LastScanService.Add(e.EventCode, @char);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timer? GetTimer(string methodName)
|
||||||
|
{
|
||||||
|
(string MethodName, Timer Timer)[] results = _Timers.Where(l => l.MethodName == methodName).ToArray();
|
||||||
|
return !results.Any() ? null : results.First().Timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ScanForNewInputs()
|
||||||
|
{
|
||||||
|
string fileName;
|
||||||
|
IEnumerable<LinuxDevice>? devices = null;
|
||||||
|
string[] files = Directory.GetFiles("/dev/input/", "event*");
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (_Readers is null || _Readers.ContainsKey(file))
|
||||||
|
continue;
|
||||||
|
devices ??= DeviceReader.Get(_AppSettings.LinuxDevicePath);
|
||||||
|
fileName = Path.GetFileName(file);
|
||||||
|
InputReader reader = new(file, _Logger);
|
||||||
|
if (devices.Any(l => !string.IsNullOrEmpty(l.Name) && l.Name.EndsWith(_AppSettings.DeviceNameEndsWith) && l.Handlers.Any(m => m == fileName)))
|
||||||
|
reader.OnKeyPress += ReaderOnOnKeyPress;
|
||||||
|
_Readers?.Add(file, reader);
|
||||||
|
}
|
||||||
|
IEnumerable<InputReader>? deadReaders = _Readers?.Values.Where(r => r.Faulted);
|
||||||
|
if (deadReaders is not null)
|
||||||
|
{
|
||||||
|
foreach (InputReader? inputReader in deadReaders)
|
||||||
|
{
|
||||||
|
_ = _Readers?.Remove(inputReader.Path);
|
||||||
|
inputReader.OnKeyPress -= ReaderOnOnKeyPress;
|
||||||
|
inputReader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ScanForNewInputs(object? sender)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{ ScanForNewInputs(); }
|
||||||
|
catch (Exception ex) { _Logger.LogError(ex, nameof(ScanForNewInputs)); }
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Timer? timer = GetTimer(nameof(ScanForNewInputs));
|
||||||
|
if (timer is not null)
|
||||||
|
{
|
||||||
|
TimeSpan timeSpan = new(DateTime.Now.AddSeconds(30).Ticks - DateTime.Now.Ticks);
|
||||||
|
_ = timer.Change((int)timeSpan.TotalMilliseconds, Timeout.Infinite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { _Logger.LogError(ex, $"{nameof(ScanForNewInputs)}-{nameof(Timer)}.{nameof(Timer.Change)}"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Write()
|
||||||
|
{
|
||||||
|
int count = _LastScanService.GetCount();
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
Result<string> result = _LastScanService.GetScan();
|
||||||
|
if (!string.IsNullOrEmpty(result.Results))
|
||||||
|
_SerialService.SerialPortWrite(count, result.Results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Write(object? sender)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{ Write(); }
|
||||||
|
catch (Exception ex) { _Logger.LogError(ex, nameof(Write)); }
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Timer? timer = GetTimer(nameof(Write));
|
||||||
|
if (timer is not null)
|
||||||
|
{
|
||||||
|
TimeSpan timeSpan = new(DateTime.Now.AddMilliseconds(_AppSettings.WriteToSerialEvery).Ticks - DateTime.Now.Ticks);
|
||||||
|
_ = timer.Change((int)timeSpan.TotalMilliseconds, Timeout.Infinite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { _Logger.LogError(ex, $"{nameof(Write)}-{nameof(Timer)}.{nameof(Timer.Change)}"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,26 +2,23 @@ using System.Text.Json;
|
|||||||
|
|
||||||
namespace Barcode.Host.Server.Models;
|
namespace Barcode.Host.Server.Models;
|
||||||
|
|
||||||
public record AppSettings(string ApiExportPath,
|
public record AppSettings(string BuildNumber,
|
||||||
string ApiLoggingContentTypes,
|
|
||||||
string ApiLoggingPathPrefixes,
|
|
||||||
string ApiLogPath,
|
|
||||||
string ApiUrl,
|
|
||||||
string AttachmentPath,
|
|
||||||
string BuildNumber,
|
|
||||||
string Company,
|
string Company,
|
||||||
string ConnectionString,
|
int ClearLastScanServiceAfter,
|
||||||
|
string DeviceNameEndsWith,
|
||||||
|
int ExpectedScanLengthA,
|
||||||
|
int ExpectedScanLengthB,
|
||||||
string GitCommitSeven,
|
string GitCommitSeven,
|
||||||
string InboundApiAllowedIPList,
|
string LinuxDevicePath,
|
||||||
bool IsDevelopment,
|
bool IsDevelopment,
|
||||||
bool IsStaging,
|
bool IsStaging,
|
||||||
string MockRoot,
|
string MockRoot,
|
||||||
string MonAResource,
|
string MonAResource,
|
||||||
string MonASite,
|
string MonASite,
|
||||||
string OI2SqlConnectionString,
|
string RootPassword,
|
||||||
string OIExportPath,
|
|
||||||
string URLs,
|
string URLs,
|
||||||
string WorkingDirectoryName)
|
string WorkingDirectoryName,
|
||||||
|
int WriteToSerialEvery)
|
||||||
{
|
{
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
@ -9,26 +9,23 @@ public class AppSettings
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
[Display(Name = "Api Export Path"), Required] public string ApiExportPath { get; set; }
|
|
||||||
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
|
|
||||||
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
|
|
||||||
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
|
|
||||||
[Display(Name = "Api URL"), Required] public string ApiUrl { get; set; }
|
|
||||||
[Display(Name = "Attachment Path"), Required] public string AttachmentPath { get; set; }
|
|
||||||
[Display(Name = "Build Number"), Required] public string BuildNumber { get; set; }
|
[Display(Name = "Build Number"), Required] public string BuildNumber { get; set; }
|
||||||
[Display(Name = "Company"), Required] public string Company { get; set; }
|
[Display(Name = "Company"), Required] public string Company { get; set; }
|
||||||
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
|
[Display(Name = "Last Scan Service Clear After"), Required] public int? ClearLastScanServiceAfter { get; set; }
|
||||||
|
[Display(Name = "Device Name Ends With"), Required] public string DeviceNameEndsWith { get; set; }
|
||||||
|
[Display(Name = "ExpectedScanLengthA"), Required] public int? ExpectedScanLengthA { get; set; }
|
||||||
|
[Display(Name = "ExpectedScanLengthB"), Required] public int? ExpectedScanLengthB { get; set; }
|
||||||
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
|
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
|
||||||
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
|
[Display(Name = "Linux Device Path"), Required] public string LinuxDevicePath { get; set; }
|
||||||
[Display(Name = "Is Development"), Required] public bool? IsDevelopment { get; set; }
|
[Display(Name = "Is Development"), Required] public bool? IsDevelopment { get; set; }
|
||||||
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
|
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
|
||||||
[Display(Name = "Mock Root"), Required] public string MockRoot { get; set; }
|
[Display(Name = "Mock Root"), Required] public string MockRoot { get; set; }
|
||||||
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
|
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
|
||||||
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
|
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
|
||||||
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
|
[Display(Name = "RootPassword"), Required] public string RootPassword { get; set; }
|
||||||
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
|
|
||||||
[Display(Name = "URLs"), Required] public string URLs { get; set; }
|
[Display(Name = "URLs"), Required] public string URLs { get; set; }
|
||||||
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
|
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
|
||||||
|
[Display(Name = "WriteToSerialEvery"), Required] public int? WriteToSerialEvery { get; set; }
|
||||||
|
|
||||||
#nullable restore
|
#nullable restore
|
||||||
|
|
||||||
@ -43,28 +40,22 @@ public class AppSettings
|
|||||||
Models.AppSettings result;
|
Models.AppSettings result;
|
||||||
if (appSettings is null)
|
if (appSettings is null)
|
||||||
throw new NullReferenceException(nameof(appSettings));
|
throw new NullReferenceException(nameof(appSettings));
|
||||||
if (appSettings.ApiExportPath is null)
|
|
||||||
throw new NullReferenceException(nameof(ApiExportPath));
|
|
||||||
if (appSettings.ApiLoggingContentTypes is null)
|
|
||||||
throw new NullReferenceException(nameof(ApiLoggingContentTypes));
|
|
||||||
if (appSettings.ApiLoggingPathPrefixes is null)
|
|
||||||
throw new NullReferenceException(nameof(ApiLoggingPathPrefixes));
|
|
||||||
if (appSettings.ApiLogPath is null)
|
|
||||||
throw new NullReferenceException(nameof(ApiLogPath));
|
|
||||||
if (appSettings.ApiUrl is null)
|
|
||||||
throw new NullReferenceException(nameof(ApiUrl));
|
|
||||||
if (appSettings.AttachmentPath is null)
|
|
||||||
throw new NullReferenceException(nameof(AttachmentPath));
|
|
||||||
if (appSettings.BuildNumber is null)
|
if (appSettings.BuildNumber is null)
|
||||||
throw new NullReferenceException(nameof(BuildNumber));
|
throw new NullReferenceException(nameof(BuildNumber));
|
||||||
if (appSettings.Company is null)
|
if (appSettings.Company is null)
|
||||||
throw new NullReferenceException(nameof(Company));
|
throw new NullReferenceException(nameof(Company));
|
||||||
if (appSettings.ConnectionString is null)
|
if (appSettings.ClearLastScanServiceAfter is null)
|
||||||
throw new NullReferenceException(nameof(ConnectionString));
|
throw new NullReferenceException(nameof(ClearLastScanServiceAfter));
|
||||||
|
if (appSettings.DeviceNameEndsWith is null)
|
||||||
|
throw new NullReferenceException(nameof(DeviceNameEndsWith));
|
||||||
|
if (appSettings.ExpectedScanLengthA is null)
|
||||||
|
throw new NullReferenceException(nameof(ExpectedScanLengthA));
|
||||||
|
if (appSettings.ExpectedScanLengthB is null)
|
||||||
|
throw new NullReferenceException(nameof(ExpectedScanLengthB));
|
||||||
if (appSettings.GitCommitSeven is null)
|
if (appSettings.GitCommitSeven is null)
|
||||||
throw new NullReferenceException(nameof(GitCommitSeven));
|
throw new NullReferenceException(nameof(GitCommitSeven));
|
||||||
if (appSettings.InboundApiAllowedIPList is null)
|
if (appSettings.LinuxDevicePath is null)
|
||||||
throw new NullReferenceException(nameof(InboundApiAllowedIPList));
|
throw new NullReferenceException(nameof(LinuxDevicePath));
|
||||||
if (appSettings.IsDevelopment is null)
|
if (appSettings.IsDevelopment is null)
|
||||||
throw new NullReferenceException(nameof(IsDevelopment));
|
throw new NullReferenceException(nameof(IsDevelopment));
|
||||||
if (appSettings.IsStaging is null)
|
if (appSettings.IsStaging is null)
|
||||||
@ -75,35 +66,32 @@ public class AppSettings
|
|||||||
throw new NullReferenceException(nameof(MonAResource));
|
throw new NullReferenceException(nameof(MonAResource));
|
||||||
if (appSettings.MonASite is null)
|
if (appSettings.MonASite is null)
|
||||||
throw new NullReferenceException(nameof(MonASite));
|
throw new NullReferenceException(nameof(MonASite));
|
||||||
if (appSettings.Oi2SqlConnectionString is null)
|
if (appSettings.RootPassword is null)
|
||||||
throw new NullReferenceException(nameof(Oi2SqlConnectionString));
|
throw new NullReferenceException(nameof(RootPassword));
|
||||||
if (appSettings.OIExportPath is null)
|
|
||||||
throw new NullReferenceException(nameof(OIExportPath));
|
|
||||||
if (appSettings.URLs is null)
|
if (appSettings.URLs is null)
|
||||||
throw new NullReferenceException(nameof(URLs));
|
throw new NullReferenceException(nameof(URLs));
|
||||||
if (appSettings.WorkingDirectoryName is null)
|
if (appSettings.WorkingDirectoryName is null)
|
||||||
throw new NullReferenceException(nameof(WorkingDirectoryName));
|
throw new NullReferenceException(nameof(WorkingDirectoryName));
|
||||||
|
if (appSettings.WriteToSerialEvery is null)
|
||||||
|
throw new NullReferenceException(nameof(WriteToSerialEvery));
|
||||||
result = new(
|
result = new(
|
||||||
appSettings.ApiExportPath,
|
|
||||||
appSettings.ApiLoggingContentTypes,
|
|
||||||
appSettings.ApiLoggingPathPrefixes,
|
|
||||||
appSettings.ApiLogPath,
|
|
||||||
appSettings.ApiUrl,
|
|
||||||
appSettings.AttachmentPath,
|
|
||||||
appSettings.BuildNumber,
|
appSettings.BuildNumber,
|
||||||
appSettings.Company,
|
appSettings.Company,
|
||||||
appSettings.ConnectionString,
|
appSettings.ClearLastScanServiceAfter.Value,
|
||||||
|
appSettings.DeviceNameEndsWith,
|
||||||
|
appSettings.ExpectedScanLengthA.Value,
|
||||||
|
appSettings.ExpectedScanLengthB.Value,
|
||||||
appSettings.GitCommitSeven,
|
appSettings.GitCommitSeven,
|
||||||
appSettings.InboundApiAllowedIPList,
|
appSettings.LinuxDevicePath,
|
||||||
appSettings.IsDevelopment.Value,
|
appSettings.IsDevelopment.Value,
|
||||||
appSettings.IsStaging.Value,
|
appSettings.IsStaging.Value,
|
||||||
appSettings.MockRoot,
|
appSettings.MockRoot,
|
||||||
appSettings.MonAResource,
|
appSettings.MonAResource,
|
||||||
appSettings.MonASite,
|
appSettings.MonASite,
|
||||||
appSettings.Oi2SqlConnectionString,
|
appSettings.RootPassword,
|
||||||
appSettings.OIExportPath,
|
|
||||||
appSettings.URLs,
|
appSettings.URLs,
|
||||||
appSettings.WorkingDirectoryName);
|
appSettings.WorkingDirectoryName,
|
||||||
|
appSettings.WriteToSerialEvery.Value);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
using Barcode.Host.Server.Models;
|
using Barcode.Host.Server.HostedService;
|
||||||
|
using Barcode.Host.Server.Models;
|
||||||
|
using Barcode.Host.Server.Services;
|
||||||
using Barcode.Host.Shared.Models;
|
using Barcode.Host.Shared.Models;
|
||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@ -35,7 +37,7 @@ public class Program
|
|||||||
public static int Main(string[] args)
|
public static int Main(string[] args)
|
||||||
{
|
{
|
||||||
LoggerConfiguration loggerConfiguration = new();
|
LoggerConfiguration loggerConfiguration = new();
|
||||||
(string assemblyName, WebApplicationOptions _) = Get(args);
|
(string assemblyName, _) = Get(args);
|
||||||
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
|
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
|
||||||
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
|
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
|
||||||
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
|
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
|
||||||
@ -49,44 +51,35 @@ public class Program
|
|||||||
ILogger log = Log.ForContext<Program>();
|
ILogger log = Log.ForContext<Program>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_ = webApplicationBuilder.Services.AddMemoryCache();
|
if (appSettings.IsStaging && appSettings.IsDevelopment)
|
||||||
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
|
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||||
|
if (appSettings.IsStaging != webApplicationBuilder.Environment.IsStaging())
|
||||||
|
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||||
|
if (appSettings.IsDevelopment != webApplicationBuilder.Environment.IsDevelopment())
|
||||||
|
throw new NotSupportedException("Please check appsettings file(s)!");
|
||||||
_ = webApplicationBuilder.Services.AddControllersWithViews();
|
_ = webApplicationBuilder.Services.AddControllersWithViews();
|
||||||
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
|
|
||||||
|
|
||||||
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
|
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
|
||||||
|
_ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>();
|
||||||
|
_ = webApplicationBuilder.Services.AddSingleton<ILastScanService, LastScanService>();
|
||||||
|
_ = webApplicationBuilder.Services.AddSingleton<ILinuxGroupManager, LinuxGroupManager>();
|
||||||
|
_ = webApplicationBuilder.Services.AddHostedService<TimedHostedService>();
|
||||||
_ = webApplicationBuilder.Services.AddSwaggerGen();
|
_ = webApplicationBuilder.Services.AddSwaggerGen();
|
||||||
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
|
|
||||||
{
|
|
||||||
sessionOptions.IdleTimeout = TimeSpan.FromSeconds(2000);
|
|
||||||
sessionOptions.Cookie.HttpOnly = true;
|
|
||||||
sessionOptions.Cookie.IsEssential = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
WebApplication webApplication = webApplicationBuilder.Build();
|
WebApplication webApplication = webApplicationBuilder.Build();
|
||||||
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
|
if (appSettings.IsDevelopment)
|
||||||
if (!webApplicationBuilder.Environment.IsDevelopment())
|
|
||||||
{
|
{
|
||||||
_ = webApplication.UseExceptionHandler("/Error");
|
|
||||||
_ = webApplication.UseHttpsRedirection();
|
|
||||||
_ = webApplication.UseHsts();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(appSettings.URLs))
|
|
||||||
{
|
|
||||||
Environment.ExitCode = -1;
|
|
||||||
webApplication.Lifetime.StopApplication();
|
|
||||||
}
|
|
||||||
_ = webApplication.UseSwagger();
|
_ = webApplication.UseSwagger();
|
||||||
|
_ = webApplication.UseDeveloperExceptionPage();
|
||||||
_ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
|
_ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
|
||||||
}
|
}
|
||||||
|
if (!appSettings.IsDevelopment)
|
||||||
|
{
|
||||||
|
_ = webApplication.UseExceptionHandler("/Error");
|
||||||
|
_ = webApplication.UseHsts();
|
||||||
|
}
|
||||||
|
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
|
||||||
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
|
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
|
||||||
_ = SerilogApplicationBuilderExtensions.UseSerilogRequestLogging(webApplication);
|
|
||||||
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
|
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
|
||||||
_ = webApplication.UseStaticFiles();
|
_ = webApplication.UseStaticFiles();
|
||||||
_ = webApplication.UseSession();
|
|
||||||
_ = webApplication.MapControllers();
|
_ = webApplication.MapControllers();
|
||||||
log.Information("Starting Web Application");
|
log.Information("Starting Web Application");
|
||||||
webApplication.Run();
|
webApplication.Run();
|
||||||
|
93
Server/Services/LastScanService.cs
Normal file
93
Server/Services/LastScanService.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using Barcode.Host.Shared.DataModels;
|
||||||
|
using Barcode.Host.Shared.KeyboardMouse;
|
||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Server.Services;
|
||||||
|
|
||||||
|
public class LastScanService : ILastScanService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly List<(EventCode EventCode, char Char)> _EventCodes;
|
||||||
|
|
||||||
|
public LastScanService() =>
|
||||||
|
_EventCodes = new();
|
||||||
|
|
||||||
|
void ILastScanService.Clear()
|
||||||
|
{
|
||||||
|
lock (_EventCodes)
|
||||||
|
_EventCodes.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILastScanService.Add(EventCode eventCode, char @char)
|
||||||
|
{
|
||||||
|
lock (_EventCodes)
|
||||||
|
_EventCodes.Add((eventCode, @char));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<string> ILastScanService.GetScan()
|
||||||
|
{
|
||||||
|
Result<string> result;
|
||||||
|
char[] chars;
|
||||||
|
lock (_EventCodes)
|
||||||
|
chars = _EventCodes.Select(l => l.Char).ToArray();
|
||||||
|
result = new() { Results = new string(chars), TotalRows = chars.Length };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ILastScanService.GetCount()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
lock (_EventCodes)
|
||||||
|
result = _EventCodes.Count;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<(EventCode, char)> ILastScanService.IncludeEventCodes()
|
||||||
|
{
|
||||||
|
List<(EventCode, char)> results = new()
|
||||||
|
{
|
||||||
|
(EventCode.A, 'A'),
|
||||||
|
(EventCode.B, 'B'),
|
||||||
|
(EventCode.C, 'C'),
|
||||||
|
(EventCode.D, 'D'),
|
||||||
|
(EventCode.E, 'E'),
|
||||||
|
(EventCode.F, 'F'),
|
||||||
|
(EventCode.G, 'G'),
|
||||||
|
(EventCode.H, 'H'),
|
||||||
|
(EventCode.I, 'I'),
|
||||||
|
(EventCode.J, 'J'),
|
||||||
|
(EventCode.K, 'K'),
|
||||||
|
(EventCode.L, 'L'),
|
||||||
|
(EventCode.M, 'M'),
|
||||||
|
(EventCode.N, 'N'),
|
||||||
|
(EventCode.O, 'O'),
|
||||||
|
(EventCode.P, 'P'),
|
||||||
|
(EventCode.Q, 'Q'),
|
||||||
|
(EventCode.R, 'R'),
|
||||||
|
(EventCode.S, 'S'),
|
||||||
|
(EventCode.T, 'T'),
|
||||||
|
(EventCode.U, 'U'),
|
||||||
|
(EventCode.V, 'V'),
|
||||||
|
(EventCode.W, 'W'),
|
||||||
|
(EventCode.X, 'X'),
|
||||||
|
(EventCode.Y, 'Y'),
|
||||||
|
(EventCode.Z, 'Z'),
|
||||||
|
(EventCode.Num0, '0'),
|
||||||
|
(EventCode.Num1, '1'),
|
||||||
|
(EventCode.Num2, '2'),
|
||||||
|
(EventCode.Num3, '3'),
|
||||||
|
(EventCode.Num4, '4'),
|
||||||
|
(EventCode.Num5, '5'),
|
||||||
|
(EventCode.Num6, '6'),
|
||||||
|
(EventCode.Num7, '7'),
|
||||||
|
(EventCode.Num8, '8'),
|
||||||
|
(EventCode.Num9, '9'),
|
||||||
|
(EventCode.Minus, '-'),
|
||||||
|
(EventCode.Dot, '.'),
|
||||||
|
(EventCode.Slash, '/'),
|
||||||
|
(EventCode.Space, ' '),
|
||||||
|
};
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,24 +1,23 @@
|
|||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
using CliWrap;
|
using CliWrap;
|
||||||
using CliWrap.Buffered;
|
using CliWrap.Buffered;
|
||||||
|
|
||||||
namespace Barcode.Host.Shared.Linux;
|
namespace Barcode.Host.Server.Services;
|
||||||
|
|
||||||
public class LinuxGroupManager : ILinuxGroupManager
|
public class LinuxGroupManager : ILinuxGroupManager
|
||||||
{
|
{
|
||||||
|
|
||||||
public async Task<bool> IsInInputGroup()
|
public async Task<bool> IsInInputGroup()
|
||||||
{
|
{
|
||||||
BufferedCommandResult result = await Cli.Wrap("id")
|
BufferedCommandResult result = await Cli.Wrap("id")
|
||||||
.ExecuteBufferedAsync();
|
.ExecuteBufferedAsync();
|
||||||
|
|
||||||
string output = result.StandardOutput;
|
string output = result.StandardOutput;
|
||||||
|
|
||||||
const StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries;
|
const StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries;
|
||||||
bool inInputGroup = output.Split(new[] { ' ' }, options)
|
bool inInputGroup = output.Split(new[] { ' ' }, options)
|
||||||
.First(p => p.StartsWith("groups"))
|
.First(p => p.StartsWith("groups"))
|
||||||
.Remove(0, "groups".Length)
|
.Remove(0, "groups".Length)
|
||||||
.Split(',', options)
|
.Split(',', options)
|
||||||
.Any(p => p.Contains("input"));
|
.Any(p => p.Contains("input"));
|
||||||
|
|
||||||
return inInputGroup;
|
return inInputGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +25,6 @@ public class LinuxGroupManager : ILinuxGroupManager
|
|||||||
{
|
{
|
||||||
using CancellationTokenSource cts = new();
|
using CancellationTokenSource cts = new();
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
_ = await Cli.Wrap("bash")
|
_ = await Cli.Wrap("bash")
|
||||||
.WithArguments($"-c \"echo '{password}' | sudo -S gpasswd -a $USER input")
|
.WithArguments($"-c \"echo '{password}' | sudo -S gpasswd -a $USER input")
|
||||||
.ExecuteBufferedAsync(cts.Token);
|
.ExecuteBufferedAsync(cts.Token);
|
||||||
@ -36,9 +34,9 @@ public class LinuxGroupManager : ILinuxGroupManager
|
|||||||
{
|
{
|
||||||
using CancellationTokenSource cts = new();
|
using CancellationTokenSource cts = new();
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
_ = await Cli.Wrap("bash")
|
_ = await Cli.Wrap("bash")
|
||||||
.WithArguments($"-c \"echo '{password}' | sudo -S reboot\"")
|
.WithArguments($"-c \"echo '{password}' | sudo -S reboot\"")
|
||||||
.ExecuteBufferedAsync(cts.Token);
|
.ExecuteBufferedAsync(cts.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
44
Server/Services/SerialService.cs
Normal file
44
Server/Services/SerialService.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using Barcode.Host.Server.Models;
|
||||||
|
using Barcode.Host.Shared.Models.Stateless;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Server.Services;
|
||||||
|
|
||||||
|
public class SerialService : ISerialService
|
||||||
|
{
|
||||||
|
|
||||||
|
private string _LastRaw;
|
||||||
|
private readonly AppSettings _AppSettings;
|
||||||
|
private readonly System.IO.Ports.SerialPort _SerialPort;
|
||||||
|
|
||||||
|
public SerialService(AppSettings appSettings)
|
||||||
|
{
|
||||||
|
_LastRaw = string.Empty;
|
||||||
|
_AppSettings = appSettings;
|
||||||
|
_SerialPort = new("/dev/ttyUSB0", 9600) { ReadTimeout = 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerialService.Open() =>
|
||||||
|
_SerialPort.Open();
|
||||||
|
|
||||||
|
void ISerialService.Close() =>
|
||||||
|
_SerialPort.Close();
|
||||||
|
|
||||||
|
void ISerialService.SerialPortWrite(int count, string raw)
|
||||||
|
{
|
||||||
|
if (raw != _LastRaw)
|
||||||
|
{
|
||||||
|
string message;
|
||||||
|
if (count == _AppSettings.ExpectedScanLengthA)
|
||||||
|
message = $" {raw[2..]} {DateTime.Now:h:m tt}";
|
||||||
|
else if (count == _AppSettings.ExpectedScanLengthB)
|
||||||
|
message = $" {raw[2..]}";
|
||||||
|
else
|
||||||
|
message = $" {raw}";
|
||||||
|
byte[] bytes = Encoding.ASCII.GetBytes(message);
|
||||||
|
_SerialPort.Write(bytes, 0, bytes.Length);
|
||||||
|
_LastRaw = raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,47 +1,13 @@
|
|||||||
{
|
{
|
||||||
"ApiExportPath": "\\\\messdv002.na.infineon.com\\Candela",
|
"ExpectedScanLengthA": 6,
|
||||||
"ApiUrl": "~/api",
|
"ExpectedScanLengthB": 9,
|
||||||
"ConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Integrated Security=True;Initial Catalog=Metrology;",
|
"Logging": {
|
||||||
"IsDevelopment": true,
|
"LogLevel": {
|
||||||
"MockRoot": "",
|
"Log4netProvider": "Debug"
|
||||||
"MonAResource": "OI_Metrology_Viewer_IFX",
|
|
||||||
"Oi2SqlConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
|
|
||||||
"Serilog": {
|
|
||||||
"Using": [
|
|
||||||
"Serilog.Sinks.Console",
|
|
||||||
"Serilog.Sinks.File"
|
|
||||||
],
|
|
||||||
"MinimumLevel": "Debug",
|
|
||||||
"WriteTo": [
|
|
||||||
{
|
|
||||||
"Name": "Debug",
|
|
||||||
"Args": {
|
|
||||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Console",
|
|
||||||
"Args": {
|
|
||||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "File",
|
|
||||||
"Args": {
|
|
||||||
"path": "%workingDirectory% - Log/log-.txt",
|
|
||||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
|
|
||||||
"rollingInterval": "Hour"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Enrich": [
|
|
||||||
"FromLogContext",
|
|
||||||
"WithMachineName",
|
|
||||||
"WithThreadId"
|
|
||||||
],
|
|
||||||
"Properties": {
|
|
||||||
"Application": "Sample"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"URLs": "https://localhost:7130;http://localhost:5126"
|
"IsDevelopment": true,
|
||||||
|
"Serilog": {
|
||||||
|
"MinimumLevel": "Debug"
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,31 +1,26 @@
|
|||||||
{
|
{
|
||||||
"AllowedHosts": "*",
|
|
||||||
"ApiExportPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si",
|
|
||||||
"ApiLoggingContentTypes": "application/json",
|
|
||||||
"ApiLoggingPathPrefixes": "/api/inbound",
|
|
||||||
"ApiUrl": "~/api",
|
|
||||||
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
|
|
||||||
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
|
|
||||||
"BuildNumber": "1",
|
"BuildNumber": "1",
|
||||||
"Company": "Infineon Technologies Americas Corp.",
|
"Company": "Infineon Technologies Americas Corp.",
|
||||||
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology;",
|
"DeviceNameEndsWith": "Symbol Bar Code Scanner",
|
||||||
|
"ExpectedScanLengthA": 8,
|
||||||
|
"ExpectedScanLengthB": 14,
|
||||||
|
"ExpectedScanLengthBExample": "1TO172125.1.11",
|
||||||
|
"ClearLastScanServiceAfter": 250,
|
||||||
"GitCommitSeven": "1234567",
|
"GitCommitSeven": "1234567",
|
||||||
|
"LinuxDevicePath": "/proc/bus/input/devices",
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
"Log4netProvider": "Debug",
|
"Log4netProvider": "Information",
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"InboundApiAllowedIPList": "",
|
|
||||||
"IsDevelopment": false,
|
"IsDevelopment": false,
|
||||||
"IsStaging": false,
|
"IsStaging": false,
|
||||||
"MockRoot": "",
|
"MockRoot": "",
|
||||||
"MonAResource": "OI_Metrology_Viewer_EC",
|
"MonAResource": "OI_Metrology_Viewer_EC",
|
||||||
"MonASite": "auc",
|
"MonASite": "auc",
|
||||||
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
|
|
||||||
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
|
|
||||||
"Serilog": {
|
"Serilog": {
|
||||||
"Using": [
|
"Using": [
|
||||||
"Serilog.Sinks.Console",
|
"Serilog.Sinks.Console",
|
||||||
@ -63,6 +58,8 @@
|
|||||||
"Application": "Sample"
|
"Application": "Sample"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"URLs": "http://localhost:5002;",
|
"RootPassword": "",
|
||||||
"WorkingDirectoryName": "IFXApps"
|
"URLs": "http://localhost:5003;",
|
||||||
|
"WorkingDirectoryName": "IFXApps",
|
||||||
|
"WriteToSerialEvery": 750
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
|
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
|
||||||
@ -19,7 +20,6 @@
|
|||||||
<DefineConstants>Linux</DefineConstants>
|
<DefineConstants>Linux</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliWrap" Version="3.6.3" />
|
|
||||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
|
7
Shared/DataModels/Result.cs
Normal file
7
Shared/DataModels/Result.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Barcode.Host.Shared.DataModels;
|
||||||
|
|
||||||
|
public class Result<T>
|
||||||
|
{
|
||||||
|
public T? Results { get; set; }
|
||||||
|
public long TotalRows { get; set; }
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
namespace Barcode.Host.Shared.KeyboardMouse.Abstract;
|
|
||||||
|
|
||||||
public interface IAggregateInputReader
|
|
||||||
{
|
|
||||||
event InputReader.RaiseKeyPress OnKeyPress;
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
using Barcode.Host.Shared.KeyboardMouse.Abstract;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Barcode.Host.Shared.KeyboardMouse;
|
|
||||||
|
|
||||||
public class AggregateInputReader : IDisposable, IAggregateInputReader
|
|
||||||
{
|
|
||||||
private readonly ILogger<InputReader> _InputReaderLogger;
|
|
||||||
|
|
||||||
private Dictionary<string, InputReader>? _Readers = new();
|
|
||||||
|
|
||||||
public event InputReader.RaiseKeyPress? OnKeyPress;
|
|
||||||
|
|
||||||
public AggregateInputReader(ILogger<InputReader> inputReaderLogger)
|
|
||||||
{
|
|
||||||
_InputReaderLogger = inputReaderLogger;
|
|
||||||
|
|
||||||
System.Timers.Timer timer = new()
|
|
||||||
{
|
|
||||||
Interval = 10 * 1000,
|
|
||||||
Enabled = true
|
|
||||||
};
|
|
||||||
timer.Elapsed += (_, _) => Scan();
|
|
||||||
timer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReaderOnOnKeyPress(KeyPressEvent e) => OnKeyPress?.Invoke(e);
|
|
||||||
|
|
||||||
private void Scan()
|
|
||||||
{
|
|
||||||
string[] files = Directory.GetFiles("/dev/input/", "event*");
|
|
||||||
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
if (_Readers is not null && _Readers.ContainsKey(file))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputReader reader = new(file, _InputReaderLogger);
|
|
||||||
|
|
||||||
reader.OnKeyPress += ReaderOnOnKeyPress;
|
|
||||||
|
|
||||||
_Readers?.Add(file, reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<InputReader>? deadReaders = _Readers?.Values.Where(r => r.Faulted);
|
|
||||||
if (deadReaders is not null)
|
|
||||||
{
|
|
||||||
foreach (InputReader? dr in deadReaders)
|
|
||||||
{
|
|
||||||
_ = _Readers?.Remove(dr.Path);
|
|
||||||
dr.OnKeyPress -= ReaderOnOnKeyPress;
|
|
||||||
dr.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_Readers is not null)
|
|
||||||
{
|
|
||||||
foreach (InputReader d in _Readers.Values)
|
|
||||||
{
|
|
||||||
d.OnKeyPress -= ReaderOnOnKeyPress;
|
|
||||||
d.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_Readers = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,66 +2,52 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public static class DeviceReader
|
public static class DeviceReader
|
||||||
{
|
{
|
||||||
public static IEnumerable<LinuxDevice> Get(string path = "/proc/bus/input/devices")
|
|
||||||
|
public static IEnumerable<LinuxDevice> Get(string path)
|
||||||
{
|
{
|
||||||
List<LinuxDevice> devices = new();
|
|
||||||
|
|
||||||
using FileStream filestream = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
||||||
using StreamReader reader = new(filestream);
|
|
||||||
|
|
||||||
LinuxDevice linuxDevice = new();
|
LinuxDevice linuxDevice = new();
|
||||||
while (!reader.EndOfStream)
|
List<LinuxDevice> linuxDevices = new();
|
||||||
|
using FileStream filestream = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
|
using StreamReader streamReader = new(filestream);
|
||||||
|
while (!streamReader.EndOfStream)
|
||||||
{
|
{
|
||||||
string? line = reader.ReadLine();
|
string? line = streamReader.ReadLine();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(line))
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(linuxDevice.Name))
|
if (!string.IsNullOrWhiteSpace(linuxDevice.Name))
|
||||||
{
|
{
|
||||||
devices.Add(linuxDevice);
|
linuxDevices.Add(linuxDevice);
|
||||||
linuxDevice = new LinuxDevice();
|
linuxDevice = new LinuxDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.StartsWith("I"))
|
if (line.StartsWith("I"))
|
||||||
ApplyIdentifier(line, linuxDevice);
|
ApplyIdentifier(line, linuxDevice);
|
||||||
|
|
||||||
else if (line.StartsWith("N"))
|
else if (line.StartsWith("N"))
|
||||||
linuxDevice.Name = line.Substring(9, line.Length - 9 - 1);
|
linuxDevice.Name = line.Substring(9, line.Length - 9 - 1);
|
||||||
|
|
||||||
else if (line.StartsWith("P"))
|
else if (line.StartsWith("P"))
|
||||||
linuxDevice.PhysicalPath = line[8..];
|
linuxDevice.PhysicalPath = line[8..];
|
||||||
|
|
||||||
else if (line.StartsWith("S"))
|
else if (line.StartsWith("S"))
|
||||||
linuxDevice.SysFsPath = line[9..];
|
linuxDevice.SysFsPath = line[9..];
|
||||||
|
|
||||||
else if (line.StartsWith("U"))
|
else if (line.StartsWith("U"))
|
||||||
linuxDevice.UniqueIdentificationCode = line[8..];
|
linuxDevice.UniqueIdentificationCode = line[8..];
|
||||||
|
|
||||||
else if (line.StartsWith("H"))
|
else if (line.StartsWith("H"))
|
||||||
linuxDevice.Handlers = line[12..]
|
linuxDevice.Handlers = line[12..]
|
||||||
.Split(" ")
|
.Split(" ")
|
||||||
.Where(h => !string.IsNullOrWhiteSpace(h))
|
.Where(h => !string.IsNullOrWhiteSpace(h))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
else if (line.StartsWith("B"))
|
else if (line.StartsWith("B"))
|
||||||
linuxDevice.Bitmaps.Add(line[3..]);
|
linuxDevice.Bitmaps.Add(line[3..]);
|
||||||
}
|
}
|
||||||
|
return linuxDevices;
|
||||||
return devices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ApplyIdentifier(string line, LinuxDevice linuxDevice)
|
private static void ApplyIdentifier(string line, LinuxDevice linuxDevice)
|
||||||
{
|
{
|
||||||
string[] values = line[3..]
|
string[] values = line[3..].Split(" ");
|
||||||
.Split(" ");
|
|
||||||
|
|
||||||
foreach (string v in values)
|
foreach (string v in values)
|
||||||
{
|
{
|
||||||
string[] kvp = v.Split("=");
|
string[] kvp = v.Split("=");
|
||||||
|
|
||||||
switch (kvp[0])
|
switch (kvp[0])
|
||||||
{
|
{
|
||||||
case "Bus":
|
case "Bus":
|
||||||
@ -79,4 +65,5 @@ public static class DeviceReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,59 +4,42 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public class InputReader : IDisposable
|
public class InputReader : IDisposable
|
||||||
{
|
{
|
||||||
private readonly ILogger<InputReader> _Logger;
|
|
||||||
|
private long _Ticks;
|
||||||
|
private bool _Disposing;
|
||||||
|
private readonly int _PiOffset;
|
||||||
private const int _BufferLength = 24;
|
private const int _BufferLength = 24;
|
||||||
|
private readonly FileStream? _FileStream;
|
||||||
private static readonly int _PiOffset;
|
private readonly ILogger<IDisposable> _Logger;
|
||||||
|
|
||||||
private readonly byte[] _Buffer = new byte[_BufferLength];
|
private readonly byte[] _Buffer = new byte[_BufferLength];
|
||||||
|
|
||||||
private FileStream? _Stream;
|
public string Path { get; init; }
|
||||||
private bool _Disposing;
|
|
||||||
|
|
||||||
public delegate void RaiseKeyPress(KeyPressEvent e);
|
|
||||||
|
|
||||||
public delegate void RaiseMouseMove(MouseMoveEvent e);
|
|
||||||
|
|
||||||
public event RaiseKeyPress? OnKeyPress;
|
|
||||||
|
|
||||||
public event RaiseMouseMove? OnMouseMove;
|
|
||||||
|
|
||||||
public string Path { get; }
|
|
||||||
|
|
||||||
public bool Faulted { get; private set; }
|
public bool Faulted { get; private set; }
|
||||||
|
|
||||||
static InputReader()
|
public event RaiseKeyPress? OnKeyPress;
|
||||||
{
|
public event RaiseMouseMove? OnMouseMove;
|
||||||
if (RunningOnRaspberryPi())
|
|
||||||
{
|
|
||||||
_PiOffset = -8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputReader(
|
public delegate void RaiseKeyPress(KeyPressEvent e);
|
||||||
string path,
|
public delegate void RaiseMouseMove(MouseMoveEvent e);
|
||||||
ILogger<InputReader> logger)
|
|
||||||
{
|
|
||||||
_Logger = logger;
|
|
||||||
|
|
||||||
|
public InputReader(string path, ILogger<IDisposable> logger)
|
||||||
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
|
_Logger = logger;
|
||||||
|
if (RunningOnRaspberryPi())
|
||||||
|
_PiOffset = -8;
|
||||||
try
|
try
|
||||||
{
|
{ _FileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); }
|
||||||
_Stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException ex)
|
catch (UnauthorizedAccessException ex)
|
||||||
{
|
{
|
||||||
_Logger.LogError(ex, "Current user doesn't have permissions to access input data. Add user to input group to correct this error");
|
logger.LogError(ex, "Current user doesn't have permissions to access input data. Add user to input group to correct this error");
|
||||||
Faulted = true;
|
Faulted = true;
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
_Logger.LogWarning(ex, $"Error occurred while trying to build stream for {path}");
|
logger.LogWarning(ex, $"Error occurred while trying to build stream for {path}");
|
||||||
Faulted = true;
|
Faulted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Task.Run(Run);
|
_ = Task.Run(Run);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,33 +49,27 @@ public class InputReader : IDisposable
|
|||||||
{
|
{
|
||||||
if (_Disposing)
|
if (_Disposing)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!Faulted && _Stream is not null)
|
if (!Faulted && _FileStream is not null)
|
||||||
{
|
_ = _FileStream.Read(_Buffer, 0, _BufferLength);
|
||||||
_ = _Stream.Read(_Buffer, 0, _BufferLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
_Logger.LogInformation(ex, $"Error occured while trying to read from the stream for {Path}");
|
_Logger.LogInformation(ex, $"Error occured while trying to read from the stream for {Path}");
|
||||||
Faulted = true;
|
Faulted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventType type = GetEventType();
|
EventType type = GetEventType();
|
||||||
short code = GetCode();
|
|
||||||
int value = GetValue();
|
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case EventType.EV_SYN:
|
||||||
|
_Ticks = DateTime.Now.Ticks;
|
||||||
|
break;
|
||||||
case EventType.EV_KEY:
|
case EventType.EV_KEY:
|
||||||
HandleKeyPressEvent(code, value);
|
HandleKeyPressEvent();
|
||||||
break;
|
break;
|
||||||
case EventType.EV_REL:
|
case EventType.EV_REL:
|
||||||
MouseAxis axis = (MouseAxis)code;
|
HandleMouseMoveEvent();
|
||||||
MouseMoveEvent e = new(axis, value);
|
|
||||||
OnMouseMove?.Invoke(e);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,9 +84,7 @@ public class InputReader : IDisposable
|
|||||||
_Buffer[22 + _PiOffset],
|
_Buffer[22 + _PiOffset],
|
||||||
_Buffer[23 + _PiOffset]
|
_Buffer[23 + _PiOffset]
|
||||||
};
|
};
|
||||||
|
|
||||||
int value = BitConverter.ToInt32(valueBits, 0);
|
int value = BitConverter.ToInt32(valueBits, 0);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,9 +95,7 @@ public class InputReader : IDisposable
|
|||||||
_Buffer[18 + _PiOffset],
|
_Buffer[18 + _PiOffset],
|
||||||
_Buffer[19 + _PiOffset]
|
_Buffer[19 + _PiOffset]
|
||||||
};
|
};
|
||||||
|
|
||||||
short code = BitConverter.ToInt16(codeBits, 0);
|
short code = BitConverter.ToInt16(codeBits, 0);
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,27 +106,35 @@ public class InputReader : IDisposable
|
|||||||
_Buffer[16 + _PiOffset],
|
_Buffer[16 + _PiOffset],
|
||||||
_Buffer[17 + _PiOffset]
|
_Buffer[17 + _PiOffset]
|
||||||
};
|
};
|
||||||
|
|
||||||
short type = BitConverter.ToInt16(typeBits, 0);
|
short type = BitConverter.ToInt16(typeBits, 0);
|
||||||
|
|
||||||
EventType eventType = (EventType)type;
|
EventType eventType = (EventType)type;
|
||||||
|
|
||||||
return eventType;
|
return eventType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleKeyPressEvent(short code, int value)
|
private void HandleKeyPressEvent()
|
||||||
{
|
{
|
||||||
EventCode c = (EventCode)code;
|
short code = GetCode();
|
||||||
KeyState s = (KeyState)value;
|
int value = GetValue();
|
||||||
KeyPressEvent e = new(c, s);
|
KeyState keyState = (KeyState)value;
|
||||||
OnKeyPress?.Invoke(e);
|
EventCode eventCode = (EventCode)code;
|
||||||
|
KeyPressEvent keyPressEvent = new(eventCode, keyState, new TimeSpan(DateTime.Now.Ticks - _Ticks));
|
||||||
|
OnKeyPress?.Invoke(keyPressEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleMouseMoveEvent()
|
||||||
|
{
|
||||||
|
short code = GetCode();
|
||||||
|
int value = GetValue();
|
||||||
|
MouseAxis axis = (MouseAxis)code;
|
||||||
|
MouseMoveEvent e = new(axis, value);
|
||||||
|
OnMouseMove?.Invoke(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_Disposing = true;
|
_Disposing = true;
|
||||||
_Stream?.Dispose();
|
_FileStream?.Dispose();
|
||||||
_Stream = null;
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool RunningOnRaspberryPi()
|
private static bool RunningOnRaspberryPi()
|
||||||
@ -163,4 +144,5 @@ public class InputReader : IDisposable
|
|||||||
bool runningOnPi = text.Any(l => l.Contains("Raspberry Pi"));
|
bool runningOnPi = text.Any(l => l.Contains("Raspberry Pi"));
|
||||||
return runningOnPi;
|
return runningOnPi;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,13 +2,16 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public readonly struct KeyPressEvent
|
public readonly struct KeyPressEvent
|
||||||
{
|
{
|
||||||
public KeyPressEvent(EventCode code, KeyState state)
|
|
||||||
|
public EventCode EventCode { get; init; }
|
||||||
|
public KeyState KeyState { get; init; }
|
||||||
|
public TimeSpan TimeSpan { get; init; }
|
||||||
|
|
||||||
|
public KeyPressEvent(EventCode eventCode, KeyState keyState, TimeSpan timeSpan)
|
||||||
{
|
{
|
||||||
Code = code;
|
EventCode = eventCode;
|
||||||
State = state;
|
KeyState = keyState;
|
||||||
|
TimeSpan = timeSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventCode Code { get; }
|
|
||||||
|
|
||||||
public KeyState State { get; }
|
|
||||||
}
|
}
|
@ -2,17 +2,14 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public class LinuxDevice
|
public class LinuxDevice
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public List<string> Bitmaps { get; set; } = new();
|
||||||
|
public List<string> Handlers { get; set; } = new();
|
||||||
public LinuxDeviceIdentifier Identifier { get; set; } = new();
|
public LinuxDeviceIdentifier Identifier { get; set; } = new();
|
||||||
|
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
public string? PhysicalPath { get; set; }
|
public string? PhysicalPath { get; set; }
|
||||||
|
|
||||||
public string? SysFsPath { get; set; }
|
public string? SysFsPath { get; set; }
|
||||||
|
|
||||||
public string? UniqueIdentificationCode { get; set; }
|
public string? UniqueIdentificationCode { get; set; }
|
||||||
|
|
||||||
public List<string> Handlers { get; set; } = new();
|
|
||||||
|
|
||||||
public List<string> Bitmaps { get; set; } = new();
|
|
||||||
}
|
}
|
@ -2,11 +2,10 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public class LinuxDeviceIdentifier
|
public class LinuxDeviceIdentifier
|
||||||
{
|
{
|
||||||
|
|
||||||
public string? Bus { get; set; }
|
public string? Bus { get; set; }
|
||||||
|
|
||||||
public string? Vendor { get; set; }
|
|
||||||
|
|
||||||
public string? Product { get; set; }
|
public string? Product { get; set; }
|
||||||
|
public string? Vendor { get; set; }
|
||||||
public string? Version { get; set; }
|
public string? Version { get; set; }
|
||||||
|
|
||||||
}
|
}
|
@ -2,13 +2,14 @@ namespace Barcode.Host.Shared.KeyboardMouse;
|
|||||||
|
|
||||||
public readonly struct MouseMoveEvent
|
public readonly struct MouseMoveEvent
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public int Amount { get; }
|
||||||
|
public MouseAxis Axis { get; }
|
||||||
|
|
||||||
public MouseMoveEvent(MouseAxis axis, int amount)
|
public MouseMoveEvent(MouseAxis axis, int amount)
|
||||||
{
|
{
|
||||||
Axis = axis;
|
Axis = axis;
|
||||||
Amount = amount;
|
Amount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MouseAxis Axis { get; }
|
|
||||||
|
|
||||||
public int Amount { get; }
|
|
||||||
}
|
}
|
10
Shared/Models/Stateless/IAggregateInputReader.cs
Normal file
10
Shared/Models/Stateless/IAggregateInputReader.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using Barcode.Host.Shared.KeyboardMouse;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
|
public interface IAggregateInputReader
|
||||||
|
{
|
||||||
|
|
||||||
|
event InputReader.RaiseKeyPress OnKeyPress;
|
||||||
|
|
||||||
|
}
|
14
Shared/Models/Stateless/ILastScanController.cs
Normal file
14
Shared/Models/Stateless/ILastScanController.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
|
public interface ILastScanController<T>
|
||||||
|
{
|
||||||
|
|
||||||
|
enum Action : int
|
||||||
|
{
|
||||||
|
Get = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetRouteName() => nameof(ILastScanController<T>)[1..^10];
|
||||||
|
T GetScan();
|
||||||
|
|
||||||
|
}
|
15
Shared/Models/Stateless/ILastScanService.cs
Normal file
15
Shared/Models/Stateless/ILastScanService.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Barcode.Host.Shared.DataModels;
|
||||||
|
using Barcode.Host.Shared.KeyboardMouse;
|
||||||
|
|
||||||
|
namespace Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
|
public interface ILastScanService
|
||||||
|
{
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
int GetCount();
|
||||||
|
Result<string> GetScan();
|
||||||
|
void Add(EventCode eventCode, char @char);
|
||||||
|
List<(EventCode, char)> IncludeEventCodes();
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
namespace Barcode.Host.Shared.Linux;
|
namespace Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
public interface ILinuxGroupManager
|
public interface ILinuxGroupManager
|
||||||
{
|
{
|
||||||
Task<bool> IsInInputGroup();
|
|
||||||
|
|
||||||
|
Task<bool> IsInInputGroup();
|
||||||
|
Task RebootSystem(string password);
|
||||||
Task AddUserToInputGroup(string password);
|
Task AddUserToInputGroup(string password);
|
||||||
|
|
||||||
Task RebootSystem(string password);
|
|
||||||
}
|
}
|
10
Shared/Models/Stateless/ISerialService.cs
Normal file
10
Shared/Models/Stateless/ISerialService.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Barcode.Host.Shared.Models.Stateless;
|
||||||
|
|
||||||
|
public interface ISerialService
|
||||||
|
{
|
||||||
|
|
||||||
|
void Open();
|
||||||
|
void Close();
|
||||||
|
void SerialPortWrite(int count, string raw);
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ internal abstract class WorkingDirectory
|
|||||||
{
|
{
|
||||||
if (!Directory.Exists(result))
|
if (!Directory.Exists(result))
|
||||||
_ = Directory.CreateDirectory(result);
|
_ = Directory.CreateDirectory(result);
|
||||||
traceFile = string.Concat(result, @"\", DateTime.Now.Ticks, ".txt");
|
traceFile = Path.Combine(result, $"{DateTime.Now.Ticks}.txt");
|
||||||
File.WriteAllText(traceFile, traceFile);
|
File.WriteAllText(traceFile, traceFile);
|
||||||
File.Delete(traceFile);
|
File.Delete(traceFile);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user