TODO: initial retropilot-server commit
parent
b26a3a6bdd
commit
ec2d421d3d
|
@ -0,0 +1,8 @@
|
|||
node_modules/
|
||||
realdata/
|
||||
worker.log
|
||||
server.log
|
||||
package-lock.json
|
||||
database.json
|
||||
config.js
|
||||
.vscode
|
|
@ -0,0 +1,80 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDeTCCAmGgAwIBAgIUM4WmqKK7pqh7zhatTsUZlVwYHAcwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCV1cxEzARBgNVBAgMClNvbWUtU3RhdGUxEzARBgNVBAoM
|
||||
ClJldHJvUGlsb3QxEzARBgNVBAMMCnJldHJvcGlsb3QwHhcNMjEwNTEzMTMwMjEw
|
||||
WhcNMzEwNTExMTMwMjEwWjBMMQswCQYDVQQGEwJXVzETMBEGA1UECAwKU29tZS1T
|
||||
dGF0ZTETMBEGA1UECgwKUmV0cm9QaWxvdDETMBEGA1UEAwwKcmV0cm9waWxvdDCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOZAGYdXNhj6T5nhueIKw2k2
|
||||
eBfW4uCjrBkHRXxOUMGg/xs99QbLWzHCLzf0dZ8zWi3WykGeB14wYBQUaWdlvKIs
|
||||
K0nnCVka+8nfUMgYvTBockpCbPCcU8Bw/m5420369s0zT2usZ8HvQOt0/JZAzb+W
|
||||
RrSyhq+Ux8Ij4IW7wGS9pyiRo/9N1JTbOUkgOgo0n2fmBZ1yAZPZeqCkZbFxaHZj
|
||||
Rc3EuP7TOQheHSg/XKToBoLWxRorHbMtGY+qU3TS+nzxhQPJs6AhE+Ntf4Pof6tV
|
||||
ep6Lcv0fiQDXvgDsVgdmPg/GnO5C1YbkjyO2xdjhV1Wa5eEWHzLOWfoxUalFgbkC
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFAJRfwdc2ww7LW/gNy7yOA3U7kAEMB8GA1UdIwQY
|
||||
MBaAFAJRfwdc2ww7LW/gNy7yOA3U7kAEMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBAEQ2+6hhNX82wkB3EPmVKz5alLarT2i7GX2yR9634R4eLax2
|
||||
Ai79edp6KbICuC5KjTRd7e/mQcT/5/YYNy2ecwAG2fGK8HrtWJJjraAbBgnO+7o1
|
||||
JCt+393F5IZ/iSFRWHTdudXdbcCcUhYs+KXBU572X731ihPsctgrn6VHZdDsK5tr
|
||||
M/vMDEnYNYZLxxysSKeCAVFGRvTvMjLkmmnfjKOTp9j/2AWmGS+emmyleIRQt2N1
|
||||
pkVP9b4hFb01L36nqiAf8zcg1yj56rMxfoC+Vaez6Guq0LaViw3/T/1luA0Yi+3z
|
||||
eUicIixgGiRp8xmmVeJngUFIp0otP8P1LXVOf0k=
|
||||
-----END CERTIFICATE-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
33:85:a6:a8:a2:bb:a6:a8:7b:ce:16:ad:4e:c5:19:95:5c:18:1c:07
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C = WW, ST = Some-State, O = RetroPilot, CN = retropilot
|
||||
Validity
|
||||
Not Before: May 13 13:02:10 2021 GMT
|
||||
Not After : May 11 13:02:10 2031 GMT
|
||||
Subject: C = WW, ST = Some-State, O = RetroPilot, CN = retropilot
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:e6:40:19:87:57:36:18:fa:4f:99:e1:b9:e2:0a:
|
||||
c3:69:36:78:17:d6:e2:e0:a3:ac:19:07:45:7c:4e:
|
||||
50:c1:a0:ff:1b:3d:f5:06:cb:5b:31:c2:2f:37:f4:
|
||||
75:9f:33:5a:2d:d6:ca:41:9e:07:5e:30:60:14:14:
|
||||
69:67:65:bc:a2:2c:2b:49:e7:09:59:1a:fb:c9:df:
|
||||
50:c8:18:bd:30:68:72:4a:42:6c:f0:9c:53:c0:70:
|
||||
fe:6e:78:db:4d:fa:f6:cd:33:4f:6b:ac:67:c1:ef:
|
||||
40:eb:74:fc:96:40:cd:bf:96:46:b4:b2:86:af:94:
|
||||
c7:c2:23:e0:85:bb:c0:64:bd:a7:28:91:a3:ff:4d:
|
||||
d4:94:db:39:49:20:3a:0a:34:9f:67:e6:05:9d:72:
|
||||
01:93:d9:7a:a0:a4:65:b1:71:68:76:63:45:cd:c4:
|
||||
b8:fe:d3:39:08:5e:1d:28:3f:5c:a4:e8:06:82:d6:
|
||||
c5:1a:2b:1d:b3:2d:19:8f:aa:53:74:d2:fa:7c:f1:
|
||||
85:03:c9:b3:a0:21:13:e3:6d:7f:83:e8:7f:ab:55:
|
||||
7a:9e:8b:72:fd:1f:89:00:d7:be:00:ec:56:07:66:
|
||||
3e:0f:c6:9c:ee:42:d5:86:e4:8f:23:b6:c5:d8:e1:
|
||||
57:55:9a:e5:e1:16:1f:32:ce:59:fa:31:51:a9:45:
|
||||
81:b9
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
02:51:7F:07:5C:DB:0C:3B:2D:6F:E0:37:2E:F2:38:0D:D4:EE:40:04
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:02:51:7F:07:5C:DB:0C:3B:2D:6F:E0:37:2E:F2:38:0D:D4:EE:40:04
|
||||
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:TRUE
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
44:36:fb:a8:61:35:7f:36:c2:40:77:10:f9:95:2b:3e:5a:94:
|
||||
b6:ab:4f:68:bb:19:7d:b2:47:de:b7:e1:1e:1e:2d:ac:76:02:
|
||||
2e:fd:79:da:7a:29:b2:02:b8:2e:4a:8d:34:5d:ed:ef:e6:41:
|
||||
c4:ff:e7:f6:18:37:2d:9e:73:00:06:d9:f1:8a:f0:7a:ed:58:
|
||||
92:63:ad:a0:1b:06:09:ce:fb:ba:35:24:2b:7e:df:dd:c5:e4:
|
||||
86:7f:89:21:51:58:74:dd:b9:d5:dd:6d:c0:9c:52:16:2c:f8:
|
||||
a5:c1:53:9e:f6:5f:bd:f5:8a:13:ec:72:d8:2b:9f:a5:47:65:
|
||||
d0:ec:2b:9b:6b:33:fb:cc:0c:49:d8:35:86:4b:c7:1c:ac:48:
|
||||
a7:82:01:51:46:46:f4:ef:32:32:e4:9a:69:df:8c:a3:93:a7:
|
||||
d8:ff:d8:05:a6:19:2f:9e:9a:6c:a5:78:84:50:b7:63:75:a6:
|
||||
45:4f:f5:be:21:15:bd:35:2f:7e:a7:aa:20:1f:f3:37:20:d7:
|
||||
28:f9:ea:b3:31:7e:80:be:55:a7:b3:e8:6b:aa:d0:b6:95:8b:
|
||||
0d:ff:4f:fd:65:b8:0d:18:8b:ed:f3:79:48:9c:22:2c:60:1a:
|
||||
24:69:f3:19:a6:55:e2:67:81:41:48:a7:4a:2d:3f:c3:f5:2d:
|
||||
75:4e:7f:49
|
||||
SHA1 Fingerprint=53:77:69:82:80:D7:A7:87:FA:05:73:06:C7:79:82:AB:3A:1B:D0:7F
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDeTCCAmGgAwIBAgIUM4WmqKK7pqh7zhatTsUZlVwYHAcwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCV1cxEzARBgNVBAgMClNvbWUtU3RhdGUxEzARBgNVBAoM
|
||||
ClJldHJvUGlsb3QxEzARBgNVBAMMCnJldHJvcGlsb3QwHhcNMjEwNTEzMTMwMjEw
|
||||
WhcNMzEwNTExMTMwMjEwWjBMMQswCQYDVQQGEwJXVzETMBEGA1UECAwKU29tZS1T
|
||||
dGF0ZTETMBEGA1UECgwKUmV0cm9QaWxvdDETMBEGA1UEAwwKcmV0cm9waWxvdDCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOZAGYdXNhj6T5nhueIKw2k2
|
||||
eBfW4uCjrBkHRXxOUMGg/xs99QbLWzHCLzf0dZ8zWi3WykGeB14wYBQUaWdlvKIs
|
||||
K0nnCVka+8nfUMgYvTBockpCbPCcU8Bw/m5420369s0zT2usZ8HvQOt0/JZAzb+W
|
||||
RrSyhq+Ux8Ij4IW7wGS9pyiRo/9N1JTbOUkgOgo0n2fmBZ1yAZPZeqCkZbFxaHZj
|
||||
Rc3EuP7TOQheHSg/XKToBoLWxRorHbMtGY+qU3TS+nzxhQPJs6AhE+Ntf4Pof6tV
|
||||
ep6Lcv0fiQDXvgDsVgdmPg/GnO5C1YbkjyO2xdjhV1Wa5eEWHzLOWfoxUalFgbkC
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFAJRfwdc2ww7LW/gNy7yOA3U7kAEMB8GA1UdIwQY
|
||||
MBaAFAJRfwdc2ww7LW/gNy7yOA3U7kAEMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBAEQ2+6hhNX82wkB3EPmVKz5alLarT2i7GX2yR9634R4eLax2
|
||||
Ai79edp6KbICuC5KjTRd7e/mQcT/5/YYNy2ecwAG2fGK8HrtWJJjraAbBgnO+7o1
|
||||
JCt+393F5IZ/iSFRWHTdudXdbcCcUhYs+KXBU572X731ihPsctgrn6VHZdDsK5tr
|
||||
M/vMDEnYNYZLxxysSKeCAVFGRvTvMjLkmmnfjKOTp9j/2AWmGS+emmyleIRQt2N1
|
||||
pkVP9b4hFb01L36nqiAf8zcg1yj56rMxfoC+Vaez6Guq0LaViw3/T/1luA0Yi+3z
|
||||
eUicIixgGiRp8xmmVeJngUFIp0otP8P1LXVOf0k=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,37D12FBFD89BC15B
|
||||
|
||||
sUpoN/V2oVSTx32FrH/H/UONQzBCraGiMbxhguOmiAVit8y+3oKd0J9J3j8ItZbT
|
||||
RI/JlLjtd+bXIM21MlUaCc6OxRL9P9y6Bq9BsjslMrkAo6fgtC7BvJrPg8pcIL6C
|
||||
kUMk4UueGXtYPMcyGWUaahPqqRQdbRc9oB8OJtAGD2KnSy96boSbTacrM+IkOTkN
|
||||
Rkczl4Jul8/wrLxNaxxivGc3Ux62T/BUmqhh7TuRFbRd53+zTsge9OVsQfs3Qs6d
|
||||
PL43AqVMiFRRk+Ed/EL/Ce4OmzLXfv2+1/8hh18MErR1lRlD/o3cg+qIso//j+aV
|
||||
0/qid0M2zEhRziZv5eUMCWLg8HWODH+u8XnVzuXYhL9UfI8Yj/C9DSOHn6JR7c/3
|
||||
VFxu0s60jEYFy2MP4hwa86zW8Ay5ogl8CqB9RZVvwNA+Q6PnLh5SEFhi4oMGJjiM
|
||||
iSgBlFb2WPmunZo9WbgnGJXb5f5vW1VZp9qS8JIxVbWDdQveXImElf5q9MEM31UT
|
||||
9ypng+yjpwGTYgNyyBgmnaUdGn4WhifjnHI81Ntuf5nxeiEmKLWSya0CA9nFwn4A
|
||||
gUf8yKkZcOlsEgGnX/CfBtVuDbus4ZqOn5aXb2WZTJzmOvg0iUtPD0u4jBiv7vcq
|
||||
WYofNcKKuVk3ej6OvIonz/8iRDy73d/9PFF2ISnV199AMnb7Zx5TAX4zNDGGb6Ba
|
||||
ReiwpAI7QekRUX2Xvcwhh3lLpJfT+tfGOkDc0yndRSl7VGLdw8BfmTgN+NnT207N
|
||||
HivlTrWwyOJmy/8UfpPFpPPcnV4CMjPzKzNBBBw55onvZTpEKUmdL3GPOk+MCvpI
|
||||
OoBDJvEWPMq1AMkXFabhKcxkNfXgTHvk73EiVAZC6N11VxTwOidHuerv/9ZIt0Co
|
||||
d2TRXbMKMLJ91Y38rtnhhtWgZpsT+IMfBYhv0QpXntkkNw/IfRyQ3FxQJjRssv+c
|
||||
CQP1n8n8o8nAnPcbIXGWx5MY8V5iZEvPfY9cTI240zjGWRdkPMGPG+80otGrxHGi
|
||||
MM1nJC0P7yruY4gNHTt+G0RoKDUE2A02fALWdq3ddH0ipy7/79x3EdNbB7RiJ/8Y
|
||||
EZ2+7YWoxyWJK4yXXuHGjuMBew5B5MJdkbpOho9S1nULLRMlLP/Tl+HQwhc/Eb09
|
||||
eaIpUWWz7sjLS57t0YlKK6thRJ5yQAL+CNbzYGOoQdS2nxFEWp4nj4ODXqiPSdeA
|
||||
w8DY5AGlKxAOEgY5E0spp4yf8VGdGrPLtfbm3l9SxAL2vnvMrWvdU1f9HeDpOKks
|
||||
kwdhYE73w48KCOZMdI0yLGOvtyuuI0Vv3B1ESGWS44LJGzwfW777ZqCqv9uoAU7g
|
||||
sfZYJlmFNtGJB7nbCkAUJ9YeMYQrNJw2LXlhVbV5jxITmGRE59agsW0YrihKnoOr
|
||||
dAD9A79wAr0P/kjGtrd7AFJglNBxCG3tPVxhqUY0QyaDJBSRT+bh4Iyx5Zd31EjC
|
||||
9KxXZxW75fGA5+uTkjKjbwy2OlPS5DvYuItfbwrBX+WEXv9B8cODCX3Utz7o5Fxc
|
||||
gFslEvipwy7tun2BhS4brUvRcuBVrph9ZMUurFCnLYj2Sp/+Kh7vBQ==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDeTCCAmGgAwIBAgIUM4WmqKK7pqh7zhatTsUZlVwYHAcwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCV1cxEzARBgNVBAgMClNvbWUtU3RhdGUxEzARBgNVBAoM
|
||||
ClJldHJvUGlsb3QxEzARBgNVBAMMCnJldHJvcGlsb3QwHhcNMjEwNTEzMTMwMjEw
|
||||
WhcNMzEwNTExMTMwMjEwWjBMMQswCQYDVQQGEwJXVzETMBEGA1UECAwKU29tZS1T
|
||||
dGF0ZTETMBEGA1UECgwKUmV0cm9QaWxvdDETMBEGA1UEAwwKcmV0cm9waWxvdDCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOZAGYdXNhj6T5nhueIKw2k2
|
||||
eBfW4uCjrBkHRXxOUMGg/xs99QbLWzHCLzf0dZ8zWi3WykGeB14wYBQUaWdlvKIs
|
||||
K0nnCVka+8nfUMgYvTBockpCbPCcU8Bw/m5420369s0zT2usZ8HvQOt0/JZAzb+W
|
||||
RrSyhq+Ux8Ij4IW7wGS9pyiRo/9N1JTbOUkgOgo0n2fmBZ1yAZPZeqCkZbFxaHZj
|
||||
Rc3EuP7TOQheHSg/XKToBoLWxRorHbMtGY+qU3TS+nzxhQPJs6AhE+Ntf4Pof6tV
|
||||
ep6Lcv0fiQDXvgDsVgdmPg/GnO5C1YbkjyO2xdjhV1Wa5eEWHzLOWfoxUalFgbkC
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFAJRfwdc2ww7LW/gNy7yOA3U7kAEMB8GA1UdIwQY
|
||||
MBaAFAJRfwdc2ww7LW/gNy7yOA3U7kAEMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBAEQ2+6hhNX82wkB3EPmVKz5alLarT2i7GX2yR9634R4eLax2
|
||||
Ai79edp6KbICuC5KjTRd7e/mQcT/5/YYNy2ecwAG2fGK8HrtWJJjraAbBgnO+7o1
|
||||
JCt+393F5IZ/iSFRWHTdudXdbcCcUhYs+KXBU572X731ihPsctgrn6VHZdDsK5tr
|
||||
M/vMDEnYNYZLxxysSKeCAVFGRvTvMjLkmmnfjKOTp9j/2AWmGS+emmyleIRQt2N1
|
||||
pkVP9b4hFb01L36nqiAf8zcg1yj56rMxfoC+Vaez6Guq0LaViw3/T/1luA0Yi+3z
|
||||
eUicIixgGiRp8xmmVeJngUFIp0otP8P1LXVOf0k=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1 @@
|
|||
1F3B1C1D27FD0A48724A10572FEE340F57F6C425
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDHjCCAgYCFB87HB0n/QpIckoQVy/uNA9X9sQlMA0GCSqGSIb3DQEBCwUAMEwx
|
||||
CzAJBgNVBAYTAldXMRMwEQYDVQQIDApTb21lLVN0YXRlMRMwEQYDVQQKDApSZXRy
|
||||
b1BpbG90MRMwEQYDVQQDDApyZXRyb3BpbG90MB4XDTIxMDUxMzE1MDEwNloXDTMx
|
||||
MDMyMjE1MDEwNlowSzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQK
|
||||
DAtNeU9yZywgSW5jLjEZMBcGA1UEAwwQKi5jb21tYWRvdGFpLmNvbTCCASIwDQYJ
|
||||
KoZIhvcNAQEBBQADggEPADCCAQoCggEBALXeelG3bjvVAHD2jKzLNixNv/pVWGdc
|
||||
aQBO4/30eZg7hsYXasMazENAmmnB2msmPbyT1u/4el+QJebj3g4QQ/ntoJOZ2a64
|
||||
gVP8RcU5n1DrCans5kM01KQzToWtLSPuFb+L3XqtLfBqW9GKC+RDBz6bmG8rUZiy
|
||||
/+eKZjl7kHvsYWCZuW4YwNAJ6N5j4r6BhK/UfAy6LTRZ8FC3i836+9FuykySRRl/
|
||||
Or8hQJND/u1+P42PA80gyu/KouvjiAhs2a8UsK0JMU6mKla8BI6rn4Kzmd8tMHLP
|
||||
5HOg47Axihd6JwpcLOzEjJX5zcHXLBrqY6g6S28Yo5NcPkV6bYrvB3MCAwEAATAN
|
||||
BgkqhkiG9w0BAQsFAAOCAQEARm6ArVT1zhmgLlloUn6L6RR2af+tXGt6X/7c7Vdy
|
||||
4n1aTLcvyrshiDGFKA4g8MobOcnJ41s1i1L9p74GyIzCN9dBtXgIhUczZ9TQgGFR
|
||||
o6bwN9IVpEvSldmeliAKtQBsFernAmYrAAak4dMEf+z8i0gNOnK/PaTNaNZDu02c
|
||||
sVgMg0Os+aTLVGOWQ8K1qe6RlmuyNJ2Fu64NLNUzwkBk+voSAiQih3i1E5TZqc5K
|
||||
vZiMHhi1xAoQ4FSYzmkdBQ9c0M7yjrmMDrfsKaGykeo4LE2lHMOgBQRrraDlw1VC
|
||||
3EkMMCgmo/45kM3LYxkzg9GpSgrul42zKhZcpGmED1zWhQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICkDCCAXgCAQAwSzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQK
|
||||
DAtNeU9yZywgSW5jLjEZMBcGA1UEAwwQKi5jb21tYWRvdGFpLmNvbTCCASIwDQYJ
|
||||
KoZIhvcNAQEBBQADggEPADCCAQoCggEBALXeelG3bjvVAHD2jKzLNixNv/pVWGdc
|
||||
aQBO4/30eZg7hsYXasMazENAmmnB2msmPbyT1u/4el+QJebj3g4QQ/ntoJOZ2a64
|
||||
gVP8RcU5n1DrCans5kM01KQzToWtLSPuFb+L3XqtLfBqW9GKC+RDBz6bmG8rUZiy
|
||||
/+eKZjl7kHvsYWCZuW4YwNAJ6N5j4r6BhK/UfAy6LTRZ8FC3i836+9FuykySRRl/
|
||||
Or8hQJND/u1+P42PA80gyu/KouvjiAhs2a8UsK0JMU6mKla8BI6rn4Kzmd8tMHLP
|
||||
5HOg47Axihd6JwpcLOzEjJX5zcHXLBrqY6g6S28Yo5NcPkV6bYrvB3MCAwEAAaAA
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAje+8fCINHo0oHOiBuc49jopLJyqvzkvIKd0rf
|
||||
vdzmb7g0DMd8e/5cyWYLsmleUwOquZhuJ4bFT2MhofnvjeWkC6o79jtPaFCxU7y5
|
||||
ABLOjyWlJCnJPVZyymTa+AlZrEVCWcYqvSozXpfdXCpN6+0O2BH2GkE7ne0nXvm1
|
||||
V1AVSMpGldD4A18CE2hFmZWU6UyStYJjE8/1K4+RJTBWgYic8LJA/UeP7u0rYhRo
|
||||
9Ex+I2LeCGZ1ocupNedbCeozZBq9NVbZ0bp4814G+GMxRS/mvOORvdf7OgyPIwsr
|
||||
bOlXZIJ/7JKp0ED5lLcRreCle+XX1op7hiee+7IzxdaeALOR
|
||||
-----END CERTIFICATE REQUEST-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAtd56UbduO9UAcPaMrMs2LE2/+lVYZ1xpAE7j/fR5mDuGxhdq
|
||||
wxrMQ0CaacHaayY9vJPW7/h6X5Al5uPeDhBD+e2gk5nZrriBU/xFxTmfUOsJqezm
|
||||
QzTUpDNOha0tI+4Vv4vdeq0t8Gpb0YoL5EMHPpuYbytRmLL/54pmOXuQe+xhYJm5
|
||||
bhjA0Ano3mPivoGEr9R8DLotNFnwULeLzfr70W7KTJJFGX86vyFAk0P+7X4/jY8D
|
||||
zSDK78qi6+OICGzZrxSwrQkxTqYqVrwEjqufgrOZ3y0wcs/kc6DjsDGKF3onClws
|
||||
7MSMlfnNwdcsGupjqDpLbxijk1w+RXptiu8HcwIDAQABAoIBADfff6i3N9B94cLS
|
||||
m+lCDQSTZlVb/urSQxfrJLQSdYDFWORmsU/7XaGTqVywR4//kZvrt27F4aKWQG6s
|
||||
tr2PVbLkxB5Ud8HrwR+yMyUiTMWpT7C6rQscoe9IK+l5iJKvRFMyfvp/Vcu0gTzg
|
||||
skKQLRuY5b3RiyHkbCYQKNOkGIFZWmF0Q5qCwRAMF2zAmw7JgflkWcpq8P8YE6Fj
|
||||
M2cNIzQloDUaWYO+EHwiBgWOWjOEASixBbdMZxv4B0/elWRdBR2FUww7jZ7L9Skw
|
||||
vgydBsgF5v2vPdFgE4uMQU9LrOP+jZ3/87TeGi4Jf3mYa4L4SUkAHxRGs63FZilj
|
||||
xJy/vfECgYEA7f645bWX5Bm/kZveU+oF+TUXVC5Y7qptoPe8MwAkI0N64wRKpTsg
|
||||
kDU5OwSB5MAVEa4+tWGSoJFH4MBh0f7+Z4Y9NpupLRtFvpjjXQkzfjFauIQNVYcp
|
||||
t2sjTgeeplDgkKkNTdZpyftulISQEhQefiaujjOGj/AbNg8hcsgweq0CgYEAw6DB
|
||||
6qX8bhvD7TUlNR89DfkLLyg+XL+q69Km6Raprf6R6ynvZrojT3+GSzB13gm7AM1b
|
||||
qw5hM2RYWdvjSz7uG/i/qt95eSwo9Zs84db1H9rcpMmwgVL4lOR8GUm1cjyZuDHJ
|
||||
HYg0k7WubKTnn/JahyvUhIuGLRy3toW23Zye7p8CgYB4uWlZPJBb6KPAXOyebGuz
|
||||
SjcXQJtkFZeeu4v/4uZx7Nz9I0QqJKAUBquNQHATdUw6t8SfhWs3f/qSC4STXWH3
|
||||
aaTLepKKivcKA8vxeaVhMe/vAS0yYWnL3ND/1+WmQAhp2RcikM0A5EXnmIbsZMBD
|
||||
BaQuBf0QLp/fADXbX6kX0QKBgBbpsUzGfDZ5Ug1qeB0st333eXPghs1eNarBVYNf
|
||||
gCg89OJSWxPxIUmiahxMZMHI6fpCE0aJvKDEVATSWGDr0f+8ttZQrm2e2n1J3Wum
|
||||
PbepbsZuSRocmbj2ugJMO9BRgL+uNRwcY+wZD4DyH58AR9IlNBMCNIj8IBhkuPJj
|
||||
8cmJAoGBAMQYsTDkS120+ei3zK5qVfAIHfQPMhKZP/NqOggTBqZVpbYHGz12JMu3
|
||||
IbwHEOJy9xIpkJiMBEiUF5P9zgl4XIp0ToD/pXvLteAAFSruellK+HiHEhxTXUVB
|
||||
OEYYgvNYoTZas2O9srmUopn144QcDNyQK6dpCYjDvTgNlgyZG9aB
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,29 @@
|
|||
var config = {
|
||||
applicationSalt: 'RANDOM_SEED',
|
||||
|
||||
databaseFile: 'database.json',
|
||||
|
||||
allowAccountRegistration: true,
|
||||
|
||||
httpInterface: '0.0.0.0',
|
||||
httpPort: 3000,
|
||||
|
||||
httpsInterface: '0.0.0.0',
|
||||
httpsPort: 4430,
|
||||
sslKey: 'certs/retropilot.key',
|
||||
sslCrt: 'certs/retropilot.crt',
|
||||
|
||||
baseUploadUrl: 'http://192.168.1.165:3000/backend/post_upload',
|
||||
|
||||
baseDriveDownloadUrl: 'http://192.168.1.165:3000/realdata/',
|
||||
baseDriveDownloadPathMapping: '/realdata', // path mapping of above download url for expressjs, prefix with "/"
|
||||
|
||||
storagePath: 'realdata/', // relative or absolute ( "/..." for absolute path )
|
||||
deviceStorageQuotaMb: 200000,
|
||||
deviceDriveQuota: 1000,
|
||||
deviceDriveExpirationDays: 30,
|
||||
|
||||
cabanaUrl: 'http://192.168.1.165:3001/'
|
||||
};
|
||||
|
||||
module.exports = config;
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "retropilot-server",
|
||||
"version": "1.0.0",
|
||||
"description": "replacement for comma.ai backend and useradmin dashboard. can be combined with a modified cabana instance.",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@commaai/log_reader": "^0.8.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"crypto": "^1.0.1",
|
||||
"directory-tree": "^2.2.9",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"fast-folder-size": "^1.3.0",
|
||||
"ffprobe": "^1.1.2",
|
||||
"ffprobe-static": "^3.0.0",
|
||||
"file-chunked": "^1.0.4",
|
||||
"htmlspecialchars": "^1.0.5",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"log4js": "^6.3.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"multer": "^1.4.2",
|
||||
"proper-lockfile": "^4.1.2",
|
||||
"sendmail": "^1.6.1"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,449 @@
|
|||
const config = require('./config');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const log4js = require('log4js');
|
||||
|
||||
const lockfile = require('proper-lockfile');
|
||||
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const bodyParser = require('body-parser');
|
||||
const cookieParser=require('cookie-parser');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const low = require('lowdb');
|
||||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
|
||||
const sendmail = require('sendmail')();
|
||||
|
||||
const htmlspecialchars = require('htmlspecialchars');
|
||||
|
||||
const dirTree = require("directory-tree");
|
||||
const { resolve } = require('path');
|
||||
|
||||
|
||||
const Reader = require('@commaai/log_reader');
|
||||
var ffprobe = require('ffprobe'),
|
||||
ffprobeStatic = require('ffprobe-static');
|
||||
const { exception } = require('console');
|
||||
|
||||
const adapter = new FileSync(config.databaseFile);
|
||||
const db = low(adapter);
|
||||
|
||||
|
||||
log4js.configure({
|
||||
appenders: { logfile: { type: "file", filename: "worker.log" }, out: { type: "console"} },
|
||||
categories: { default: { appenders: ['out', 'logfile'], level: 'info' } }
|
||||
});
|
||||
|
||||
var logger = log4js.getLogger('default');
|
||||
|
||||
|
||||
function initializeDatabase() {
|
||||
db.read();
|
||||
if (!db.has('devices').value()) {
|
||||
logger.error("database not initialized, exit worker");
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
function initializeStorage() {
|
||||
var verifiedPath = mkDirByPathSync(config.storagePath, {isRelativeToScript: (config.storagePath.indexOf("/")===0 ? false : true)});
|
||||
if (verifiedPath!=null)
|
||||
logger.info("Verified storage path "+verifiedPath);
|
||||
else {
|
||||
logger.error("Unable to verify storage path '"+config.storagePath+"', check filesystem / permissions");
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function validateJWTToken(token, publicKey) {
|
||||
try {
|
||||
var decoded = jwt.verify(token.replace("JWT ", ""), publicKey, { algorithms: ['RS256'] });
|
||||
return decoded;
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function formatDate(timestampMs) {
|
||||
return new Date(timestampMs).toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
||||
}
|
||||
|
||||
function formatDuration(durationSeconds) {
|
||||
var secs = durationSeconds % 60;
|
||||
var mins = Math.floor(durationSeconds / 60);
|
||||
var hours = Math.floor(mins / 60);
|
||||
mins = mins % 60;
|
||||
|
||||
var response='';
|
||||
if (hours>0) response+=hours+'h ';
|
||||
if (hours>0 || mins>0) response+=mins+'m ';
|
||||
response+=secs+'s';
|
||||
return response;
|
||||
}
|
||||
|
||||
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
|
||||
const sep = path.sep;
|
||||
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
||||
const baseDir = isRelativeToScript ? __dirname : '.';
|
||||
|
||||
return targetDir.split(sep).reduce((parentDir, childDir) => {
|
||||
const curDir = path.resolve(baseDir, parentDir, childDir);
|
||||
try {
|
||||
fs.mkdirSync(curDir);
|
||||
} catch (err) {
|
||||
if (err.code === 'EEXIST') { // curDir already exists!
|
||||
return curDir;
|
||||
}
|
||||
|
||||
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
|
||||
if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
|
||||
logger.error(`EACCES: permission denied, mkdir '${parentDir}'`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
|
||||
if (!caughtErr || (caughtErr && curDir === path.resolve(targetDir))) {
|
||||
logger.error("'EACCES', 'EPERM', 'EISDIR' during mkdir");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return curDir;
|
||||
}, initDir);
|
||||
}
|
||||
|
||||
function simpleStringify (object){
|
||||
var simpleObject = {};
|
||||
for (var prop in object ){
|
||||
if (!object.hasOwnProperty(prop)){
|
||||
continue;
|
||||
}
|
||||
if (typeof(object[prop]) == 'object'){
|
||||
continue;
|
||||
}
|
||||
if (typeof(object[prop]) == 'function'){
|
||||
continue;
|
||||
}
|
||||
simpleObject[prop] = object[prop];
|
||||
}
|
||||
return JSON.stringify(simpleObject); // returns cleaned up JSON
|
||||
};
|
||||
|
||||
function writeFileSync(path, buffer, permission) {
|
||||
var fileDescriptor;
|
||||
try {
|
||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||
} catch (e) {
|
||||
fs.chmodSync(path, permission);
|
||||
fileDescriptor = fs.openSync(path, 'w', permission);
|
||||
}
|
||||
|
||||
if (fileDescriptor) {
|
||||
fs.writeSync(fileDescriptor, buffer, 0, buffer.length, 0);
|
||||
fs.closeSync(fileDescriptor);
|
||||
logger.info("writeFileSync wiriting to '"+path+"' successful");
|
||||
return true;
|
||||
}
|
||||
logger.error("writeFileSync writing to '"+path+"' failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
function moveUploadedFile(buffer, directory, filename) {
|
||||
logger.info("moveUploadedFile called with '"+filename+"' -> '"+directory+"'");
|
||||
|
||||
if (directory.indexOf("..")>=0 || filename.indexOf("..")>=0) {
|
||||
logger.error("moveUploadedFile failed, .. in directory or filename");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config.storagePath.lastIndexOf("/")!==config.storagePath.length-1)
|
||||
directory='/'+directory;
|
||||
if (directory.lastIndexOf("/")!==directory.length-1)
|
||||
directory=directory+'/';
|
||||
|
||||
var finalPath = mkDirByPathSync(config.storagePath+directory, {isRelativeToScript: (config.storagePath.indexOf("/")===0 ? false : true)});
|
||||
if (finalPath && finalPath.length>0) {
|
||||
if (writeFileSync(finalPath+"/"+filename, buffer, 0o660)) {
|
||||
logger.info("moveUploadedFile successfully written '"+(finalPath+"/"+filename)+"'");
|
||||
return finalPath+"/"+filename;
|
||||
}
|
||||
logger.error("moveUploadedFile failed to writeFileSync");
|
||||
return false;
|
||||
}
|
||||
logger.error("moveUploadedFile invalid final path, check permissions to create / write '"+(config.storagePath+directory)+"'");
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
var segmentProcessQueue=[];
|
||||
var segmentProcessPosition=0;
|
||||
|
||||
var affectedDrives={};
|
||||
|
||||
var rlog_lastTs=0;
|
||||
var rlog_prevLat=-1000;
|
||||
var rlog_prevLng=-1000;
|
||||
var rlog_totalDist = 0;
|
||||
var qcamera_duration = 0;
|
||||
|
||||
function processSegmentRLog(rLogPath) {
|
||||
|
||||
rlog_lastTs=0;
|
||||
rlog_prevLat=-1000;
|
||||
rlog_prevLng=-1000;
|
||||
rlog_totalDist = 0;
|
||||
|
||||
return new Promise(
|
||||
function(resolve, reject) {
|
||||
var readStream = fs.createReadStream(rLogPath);
|
||||
var reader = Reader(readStream);
|
||||
readStream.on('close', function () {
|
||||
resolve();
|
||||
});
|
||||
|
||||
reader(function (obj) {
|
||||
try {
|
||||
if (obj['LogMonoTime']!==undefined && obj['LogMonoTime']-rlog_lastTs>=1000000*1000*1 && obj['GpsLocation']!==undefined) {
|
||||
logger.info('processSegmentRLog GpsLocation @ '+obj['LogMonoTime']+': '+obj['GpsLocation']['Latitude']+' '+obj['GpsLocation']['Longitude']);
|
||||
|
||||
if (rlog_prevLat!=-1000) {
|
||||
var lat1=rlog_prevLat;
|
||||
var lat2=obj['GpsLocation']['Latitude'];
|
||||
var lon1=rlog_prevLng;
|
||||
var lon2=obj['GpsLocation']['Longitude'];
|
||||
var p = 0.017453292519943295; // Math.PI / 180
|
||||
var c = Math.cos;
|
||||
var a = 0.5 - c((lat2 - lat1) * p)/2 +
|
||||
c(lat1 * p) * c(lat2 * p) *
|
||||
(1 - c((lon2 - lon1) * p))/2;
|
||||
|
||||
var dist_m = 1000 * 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
|
||||
rlog_totalDist+=dist_m;
|
||||
//console.log('---> distance traveled is: '+dist_m);
|
||||
}
|
||||
rlog_prevLat=obj['GpsLocation']['Latitude'];
|
||||
rlog_prevLng=obj['GpsLocation']['Longitude'];
|
||||
rlog_lastTs = obj['LogMonoTime'];
|
||||
}
|
||||
} catch(exception) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function processSegmentVideo(qcameraPath) {
|
||||
qcamera_duration=0;
|
||||
return new Promise(function(resolve, reject) {
|
||||
ffprobe(qcameraPath, { path: ffprobeStatic.path })
|
||||
.then(function (info) {
|
||||
if (info['streams']!==undefined && info['streams'][0]!==undefined && info['streams'][0]['duration']!==undefined)
|
||||
qcamera_duration = info['streams'][0]['duration'];
|
||||
logger.info('processSegmentVideo duration: '+qcamera_duration+'s');
|
||||
resolve();
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error(err);
|
||||
logger.error('processSegmentVideo error: '+err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function processSegmentsRecursive() {
|
||||
if (segmentProcessQueue.length<=segmentProcessPosition)
|
||||
return updateDrives();
|
||||
|
||||
var segmentWrapper = segmentProcessQueue[segmentProcessPosition];
|
||||
var segment = db.get('drive_segments').find({dongle_id: segmentWrapper.segment.dongle_id, drive_identifier: segmentWrapper.segment.drive_identifier, segment_id: segmentWrapper.segment.segment_id});
|
||||
const uploadComplete = segmentWrapper.uploadComplete;
|
||||
const driveIdentifier = segmentWrapper.driveIdentifier;
|
||||
const fileStatus = segmentWrapper.fileStatus;
|
||||
|
||||
logger.info('processSegmentsRecursive '+segment.value().dongle_id+' '+segment.value().drive_identifier+' '+segment.value().segment_id);
|
||||
|
||||
var p1 = processSegmentRLog(fileStatus['rlog.bz2']);
|
||||
var p2 = processSegmentVideo(fileStatus['qcamera.ts']);
|
||||
Promise.all([p1, p2]).then((values) => {
|
||||
logger.info('processSegmentsRecursive '+segment.value().dongle_id+' '+segment.value().drive_identifier+' '+segment.value().segment_id+' '+(Math.round(rlog_totalDist*100)/100)+'m, duration: '+qcamera_duration+'s');
|
||||
|
||||
var updates={duration: qcamera_duration, distance_meters: Math.round(rlog_totalDist*10)/10, is_processed: true, upload_complete: uploadComplete, is_stalled: false};
|
||||
segment.assign(updates).write();
|
||||
|
||||
affectedDrives[driveIdentifier]=true;
|
||||
|
||||
segmentProcessPosition++;
|
||||
setTimeout(function() {processSegmentsRecursive();}, 0);
|
||||
}).catch(function () { });
|
||||
}
|
||||
|
||||
function updateSegments() {
|
||||
segmentProcessQueue=[];
|
||||
segmentProcessPosition=0;
|
||||
affectedDrives={};
|
||||
|
||||
drive_segments = db.get('drive_segments').filter({upload_complete: false, is_stalled: false}).sortBy('created').take(10000).value();
|
||||
for (var t=0; t<drive_segments.length; t++) {
|
||||
var segment = drive_segments[t];
|
||||
|
||||
var dongleIdHash = crypto.createHmac('sha256', config.applicationSalt).update(segment.dongle_id).digest('hex');
|
||||
var driveIdentifierHash = crypto.createHmac('sha256', config.applicationSalt).update(segment.drive_identifier).digest('hex');
|
||||
|
||||
const directoryTree = dirTree(config.storagePath+segment.dongle_id+"/"+dongleIdHash+"/"+driveIdentifierHash+"/"+segment.drive_identifier+"/"+segment.segment_id);
|
||||
var qcamera = false;
|
||||
var fcamera = false;
|
||||
var dcamera = false;
|
||||
var qlog = false;
|
||||
var rlog = false;
|
||||
var fileStatus = {'fcamera.hevc': false, 'dcamera.hevc' : false, 'qcamera.ts': false, 'qlog.bz2' : false, 'rlog.bz2' : false};
|
||||
|
||||
for (var i in directoryTree.children) {
|
||||
fileStatus[directoryTree.children[i].name]=directoryTree.children[i].path;
|
||||
}
|
||||
|
||||
|
||||
var uploadComplete=false;
|
||||
if (fileStatus['qcamera.ts']!==false && fileStatus['fcamera.hevc']!==false && fileStatus['rlog.bz2']!==false && fileStatus['qlog.bz2']!==false) // upload complete
|
||||
uploadComplete=true;
|
||||
|
||||
if (fileStatus['qcamera.ts']!==false && fileStatus['rlog.bz2']!==false && !segment.is_processed) { // can process
|
||||
segmentProcessQueue.push({segment: segment, fileStatus: fileStatus, uploadComplete: uploadComplete, driveIdentifier: segment.dongle_id+"|"+segment.drive_identifier});
|
||||
}
|
||||
else if (uploadComplete) {
|
||||
logger.info('updateSegments uploadComplete for '+segment.dongle_id+' '+segment.drive_identifier+' '+segment.segment_id);
|
||||
var updateSegment = db.get('drive_segments').find({dongle_id: segment.dongle_id, drive_identifier: segment.drive_identifier, segment_id: segment.segment_id});
|
||||
var updates={upload_complete: true, is_stalled: false};
|
||||
updateSegment.assign(updates).write();
|
||||
affectedDrives[segment.dongle_id+"|"+segment.drive_identifier]=true;
|
||||
}
|
||||
else if (Date.now()-segment.created>10*24*3600*1000) { // ignore non-uploaded segments after 10 days until a new upload_url is requested (which resets is_stalled)
|
||||
logger.info('updateSegments isStalled for '+segment.dongle_id+' '+segment.drive_identifier+' '+segment.segment_id);
|
||||
var updateSegment = db.get('drive_segments').find({dongle_id: segment.dongle_id, drive_identifier: segment.drive_identifier, segment_id: segment.segment_id});
|
||||
var updates={is_stalled: true};
|
||||
updateSegment.assign(updates).write();
|
||||
}
|
||||
|
||||
if (segmentProcessQueue.length>50) // we process at most 50 segments per batch
|
||||
break;
|
||||
}
|
||||
|
||||
if (segmentProcessQueue.length>0)
|
||||
processSegmentsRecursive();
|
||||
else // if no data is to be collected, call updateDrives to update those where eventually just the last segment completed the upload
|
||||
updateDrives();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function updateDrives() {
|
||||
// go through all affected drives and update them / complete and/or build m3u8
|
||||
logger.info("updateDrives - affected drives: "+JSON.stringify(affectedDrives));
|
||||
for (const [key, value] of Object.entries(affectedDrives)) {
|
||||
[dongleId, driveIdentifier] = key.split('|');
|
||||
var drive = db.get('drives').find({ identifier: driveIdentifier, dongle_id: dongleId});
|
||||
if (!drive.value()) continue;
|
||||
|
||||
var dongleIdHash = crypto.createHmac('sha256', config.applicationSalt).update(drive.value().dongle_id).digest('hex');
|
||||
var driveIdentifierHash = crypto.createHmac('sha256', config.applicationSalt).update(drive.value().identifier).digest('hex');
|
||||
var driveUrl=config.baseDriveDownloadUrl+drive.value().dongle_id+"/"+dongleIdHash+"/"+driveIdentifierHash+"/"+drive.value().identifier;
|
||||
var drivePath=config.storagePath+drive.value().dongle_id+"/"+dongleIdHash+"/"+driveIdentifierHash+"/"+drive.value().identifier;
|
||||
|
||||
var uploadComplete=true;
|
||||
var isProcessed=true;
|
||||
|
||||
var totalDistanceMeters=0;
|
||||
var totalDurationSeconds=0;
|
||||
var playlistSegmentStrings='';
|
||||
|
||||
drive_segments = db.get('drive_segments').filter({drive_identifier: driveIdentifier, dongle_id: dongleId}).sortBy('created').take(10000).value();
|
||||
for (var t=0; t<drive_segments.length; t++) {
|
||||
if (!drive_segments[t].upload_complete) uploadComplete=false;
|
||||
if (!drive_segments[t].is_processed) isProcessed=false;
|
||||
else {
|
||||
totalDistanceMeters+=parseFloat(drive_segments[t].distance_meters);
|
||||
totalDurationSeconds+=parseFloat(drive_segments[t].duration);
|
||||
|
||||
playlistSegmentStrings+=`#EXTINF:`+drive_segments[t].duration+`,`+drive_segments[t].segment_id+`\n`+
|
||||
driveUrl+`/`+drive_segments[t].segment_id+`/qcamera.ts\n`;
|
||||
}
|
||||
}
|
||||
|
||||
var updates = {distance_meters: Math.round(totalDistanceMeters), duration: totalDurationSeconds, upload_complete : uploadComplete, is_processed : isProcessed};
|
||||
if (uploadComplete) {
|
||||
updates['filesize'] = 0;
|
||||
const execSync = require('child_process').execSync;
|
||||
try {
|
||||
var dongleIdHash = crypto.createHmac('sha256', config.applicationSalt).update(dongleId).digest('hex');
|
||||
var driveIdentifierHash = crypto.createHmac('sha256', config.applicationSalt).update(driveIdentifier).digest('hex');
|
||||
updates['filesize'] = parseInt(execSync("du -s "+drivePath+" | awk -F'\t' '{print $1;}'").toString()); // in kilobytes
|
||||
}
|
||||
catch (exception) {}
|
||||
}
|
||||
logger.info("updateDrives drive "+dongleId+" "+driveIdentifier+" uploadComplete: "+JSON.stringify(updates));
|
||||
drive.assign(updates).write();
|
||||
|
||||
if (isProcessed) {
|
||||
// create the playlist file m3u8 for cabana
|
||||
var playlist = `#EXTM3U\n`+
|
||||
`#EXT-X-VERSION:3\n`+
|
||||
`#EXT-X-TARGETDURATION:61\n`+
|
||||
`#EXT-X-MEDIA-SEQUENCE:0\n`+
|
||||
`#EXT-X-PLAYLIST-TYPE:VOD\n`+
|
||||
playlistSegmentStrings+`\n`+
|
||||
`#EXT-X-ENDLIST`;
|
||||
|
||||
fs.writeFileSync(drivePath+'/qcamera.m3u8', playlist);
|
||||
}
|
||||
|
||||
}
|
||||
setTimeout(function() {mainWorkerLoop();}, 0);
|
||||
}
|
||||
|
||||
function deleteExpiredDrives() {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
||||
function removeDeletedDrivesPhysically() {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
||||
function mainWorkerLoop() {
|
||||
if (Date.now()-startTime>60*3600*1000) {
|
||||
logger.info("EXIT WORKER AFTER 1 HOUR TO PREVENT MEMORY LEAKS...");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
deleteExpiredDrives();
|
||||
removeDeletedDrivesPhysically();
|
||||
|
||||
setTimeout(function() {updateSegments();}, 5000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
startTime=Date.now();
|
||||
|
||||
lockfile.lock('retropilot_worker.lock', { realpath: false, stale: 30000, update: 2000 })
|
||||
.then((release) => {
|
||||
logger.info("STARTING WORKER...");
|
||||
initializeDatabase();
|
||||
initializeStorage();
|
||||
setTimeout(function() {mainWorkerLoop();}, 0);
|
||||
}).catch((e) => {
|
||||
console.error(e)
|
||||
process.exit();
|
||||
});
|
Loading…
Reference in New Issue