Compare commits
No commits in common. "master" and "webSockets" have entirely different histories.
master
...
webSockets
20
README.md
20
README.md
@ -1,19 +1 @@
|
||||
# 🐱Cat 🔫Cannon
|
||||
|
||||
The Cat Cannon is an automatically aiming water cannon designed to keep cats out of any location in which there presence is not desired. This solution is built on top of the Raspberry Pi driven by TypeScript and very little Python.
|
||||
|
||||
## Software Setup
|
||||
|
||||
Clone this repo and navigate to its saved directory
|
||||
|
||||
npm install
|
||||
|
||||
ts-node ./src/Robitics/main.ts
|
||||
|
||||
open a browser at http://localhost:5005
|
||||
|
||||
wait for cat to enter view of camera
|
||||
|
||||
what the machine protect your assets
|
||||
|
||||
|
||||
# 🐱Cat 🔫Cannon
|
||||
4
dist/Vision/main.js
vendored
4
dist/Vision/main.js
vendored
File diff suppressed because one or more lines are too long
212
package-lock.json
generated
212
package-lock.json
generated
@ -96,11 +96,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/component-emitter": {
|
||||
"version": "1.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
|
||||
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
||||
@ -110,25 +105,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg=="
|
||||
},
|
||||
"@types/cors": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz",
|
||||
"integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg=="
|
||||
},
|
||||
"@types/engine.io": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.5.tgz",
|
||||
"integrity": "sha512-DLVpLEGTEZGBXOYoYoagHSxXkDHONc0fZouF2ayw7Q18aRu1Afwci+1CFKvPpouCUOVWP+dmCaAWpQjswe7kpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz",
|
||||
@ -252,32 +228,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/socket.io": {
|
||||
"version": "2.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.12.tgz",
|
||||
"integrity": "sha512-oStc5VFkpb0AsjOxQUj9ztX5Iziatyla/rjZTYbFGoVrrKwd+JU2mtxk7iSl5RGYx9WunLo6UXW1fBzQok/ZyA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/engine.io": "*",
|
||||
"@types/node": "*",
|
||||
"@types/socket.io-parser": "*"
|
||||
}
|
||||
},
|
||||
"@types/socket.io-client": {
|
||||
"version": "1.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.35.tgz",
|
||||
"integrity": "sha512-MI8YmxFS+jMkIziycT5ickBWK1sZwDwy16mgH/j99Mcom6zRG/NimNGQ3vJV0uX5G6g/hEw0FG3w3b3sT5OUGw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/socket.io-parser": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-2.2.1.tgz",
|
||||
"integrity": "sha512-+JNb+7N7tSINyXPxAJb62+NcpC1x/fPn7z818W4xeNCdPTp6VsO/X8fCsg6+ug4a56m1v9sEiTIIUKVupcHOFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/webgl-ext": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz",
|
||||
@ -769,11 +719,6 @@
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"dev": true
|
||||
},
|
||||
"backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@ -835,16 +780,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"base64-arraybuffer": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
|
||||
"integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
|
||||
},
|
||||
"base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||
},
|
||||
"batch": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
|
||||
@ -1194,7 +1129,8 @@
|
||||
"component-emitter": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
|
||||
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
|
||||
"dev": true
|
||||
},
|
||||
"compressible": {
|
||||
"version": "2.0.18",
|
||||
@ -1283,15 +1219,6 @@
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"requires": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
@ -1317,6 +1244,7 @@
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
@ -1324,7 +1252,8 @@
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1511,64 +1440,6 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"engine.io": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.0.tgz",
|
||||
"integrity": "sha512-vW7EAtn0HDQ4MtT5QbmCHF17TaYLONv2/JwdYsq9USPRZVM4zG7WB3k0Nc321z8EuSOlhGokrYlYx4176QhD0A==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "~0.4.1",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~4.0.0",
|
||||
"ws": "~7.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
|
||||
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz",
|
||||
"integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.0.tgz",
|
||||
"integrity": "sha512-OUmn4m71/lW3ixICv4h3DuBRuh3ri0w3cDuepjsrINSbbqbni4Xw1shTFiKhl0v58lEtNpwJTpSKJJ3fondu5Q==",
|
||||
"requires": {
|
||||
"base64-arraybuffer": "0.1.4",
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~4.0.1",
|
||||
"has-cors": "1.1.0",
|
||||
"parseqs": "0.0.6",
|
||||
"parseuri": "0.0.6",
|
||||
"ws": "~7.4.2",
|
||||
"xmlhttprequest-ssl": "~1.5.4",
|
||||
"yeast": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz",
|
||||
"integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz",
|
||||
"integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==",
|
||||
"requires": {
|
||||
"base64-arraybuffer": "0.1.4"
|
||||
}
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
|
||||
@ -2169,11 +2040,6 @@
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-cors": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
|
||||
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@ -3088,7 +2954,8 @@
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
@ -3274,16 +3141,6 @@
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"parseqs": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
|
||||
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
|
||||
},
|
||||
"parseuri": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
|
||||
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
@ -4089,51 +3946,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"socket.io": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.0.tgz",
|
||||
"integrity": "sha512-Aqg2dlRh6xSJvRYK31ksG65q4kmBOqU4g+1ukhPcoT6wNGYoIwSYPlCPuRwOO9pgLUajojGFztl6+V2opmKcww==",
|
||||
"requires": {
|
||||
"@types/cookie": "^0.4.0",
|
||||
"@types/cors": "^2.8.8",
|
||||
"@types/node": "^14.14.10",
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io": "~4.1.0",
|
||||
"socket.io-adapter": "~2.1.0",
|
||||
"socket.io-parser": "~4.0.3"
|
||||
}
|
||||
},
|
||||
"socket.io-adapter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz",
|
||||
"integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg=="
|
||||
},
|
||||
"socket.io-client": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.1.0.tgz",
|
||||
"integrity": "sha512-T4qPOL80KnoBwkdR70zMpiR6aH6zv3ZqLNriofHqsO9wvQllNTOez0mpV4GdVqo1Y55Z+h8YOlBo7c8pOxDlHw==",
|
||||
"requires": {
|
||||
"@types/component-emitter": "^1.2.10",
|
||||
"backo2": "~1.0.2",
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-client": "~4.1.0",
|
||||
"parseuri": "0.0.6",
|
||||
"socket.io-parser": "~4.0.4"
|
||||
}
|
||||
},
|
||||
"socket.io-parser": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz",
|
||||
"integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==",
|
||||
"requires": {
|
||||
"@types/component-emitter": "^1.2.10",
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~4.3.1"
|
||||
}
|
||||
},
|
||||
"sockjs": {
|
||||
"version": "0.3.21",
|
||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz",
|
||||
@ -5327,11 +5139,6 @@
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"xmlhttprequest-ssl": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
|
||||
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
|
||||
@ -5356,11 +5163,6 @@
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
|
||||
},
|
||||
"yeast": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
|
||||
},
|
||||
"yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
||||
10
package.json
10
package.json
@ -4,9 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "ts-node ./src/Robotics/main.ts",
|
||||
"vision": "webpack serve",
|
||||
"build": "webpack",
|
||||
"start": "webpack serve",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
@ -14,14 +12,10 @@
|
||||
"dependencies": {
|
||||
"@tensorflow-models/coco-ssd": "^2.2.1",
|
||||
"@tensorflow/tfjs": "^2.8.2",
|
||||
"express": "^4.17.1",
|
||||
"socket.io": "^3.1.0",
|
||||
"socket.io-client": "^3.1.0"
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.11",
|
||||
"@types/socket.io": "^2.1.12",
|
||||
"@types/socket.io-client": "^1.4.35",
|
||||
"ts-loader": "^8.0.13",
|
||||
"typescript": "^4.1.3",
|
||||
"webpack": "^5.11.1",
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import IEventManager from '../Interfaces/IEventManager'
|
||||
|
||||
let instance: EventManager | null = null
|
||||
|
||||
class EventManager implements IEventManager {
|
||||
eventEmitter: EventEmitter
|
||||
|
||||
constructor () {
|
||||
if (!instance) instance = this
|
||||
|
||||
this.eventEmitter = new EventEmitter()
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
listen = (eventName: string, callback: any) => {
|
||||
this.eventEmitter.addListener(eventName, callback)
|
||||
}
|
||||
|
||||
emit = (eventName: string, detail: any) => {
|
||||
this.eventEmitter.emit(eventName, detail)
|
||||
}
|
||||
}
|
||||
|
||||
export default EventManager
|
||||
@ -1,17 +0,0 @@
|
||||
import IMotor from "../Interfaces/IMotor"
|
||||
|
||||
class Motor implements IMotor {
|
||||
public pinOne: number
|
||||
public pinTwo: number
|
||||
public pinThree: number
|
||||
public pinFour: number
|
||||
|
||||
constructor (props: IMotor) {
|
||||
this.pinOne = props.pinOne
|
||||
this.pinTwo = props.pinTwo
|
||||
this.pinThree = props.pinThree
|
||||
this.pinFour = props.pinFour
|
||||
}
|
||||
}
|
||||
|
||||
export default Motor
|
||||
@ -1,70 +0,0 @@
|
||||
import IMotor from "../Interfaces/IMotor"
|
||||
import makeMotor from "../UseCases/Factories/makeMotor"
|
||||
import * as childProcesses from 'child_process'
|
||||
import IMotorMoverConstructor from "../Interfaces/IMotorMoverConstructor"
|
||||
import IMotorMover from "../Interfaces/IMotorMover"
|
||||
|
||||
class MotorMover implements IMotorMover {
|
||||
motor: IMotor
|
||||
moveProcess: childProcesses.ChildProcessWithoutNullStreams | null = null
|
||||
pauseIntervalTime: number
|
||||
movementState: 'CLOCKWISE' | 'COUNTERCLOCKWISE' | "IDLE" = 'IDLE'
|
||||
|
||||
constructor (props: IMotorMoverConstructor) {
|
||||
this.motor = makeMotor(props.motor)
|
||||
this.pauseIntervalTime = props.pauseIntervalTime
|
||||
}
|
||||
|
||||
public moveClockwise = () => {
|
||||
if (this.movementState === 'CLOCKWISE') return
|
||||
else {
|
||||
if (!this.moveProcess?.killed) this.moveProcess?.kill()
|
||||
}
|
||||
|
||||
const motorProcessArguments = [
|
||||
'src/Robotics/moveStepper.py',
|
||||
this.motor.pinOne.toString(),
|
||||
this.motor.pinTwo.toString(),
|
||||
this.motor.pinThree.toString(),
|
||||
this.motor.pinFour.toString(),
|
||||
'clockwise',
|
||||
this.pauseIntervalTime.toString()
|
||||
]
|
||||
|
||||
console.log('start clockwise')
|
||||
this.moveProcess = childProcesses.spawn('python', motorProcessArguments)
|
||||
this.movementState = 'CLOCKWISE'
|
||||
}
|
||||
|
||||
public moveCounterClockwise = () => {
|
||||
if (this.movementState === 'COUNTERCLOCKWISE') return
|
||||
else {
|
||||
if (!this.moveProcess?.killed) this.moveProcess?.kill()
|
||||
}
|
||||
|
||||
const motorProcessArguments = [
|
||||
'src/Robotics/moveStepper.py',
|
||||
this.motor.pinOne.toString(),
|
||||
this.motor.pinTwo.toString(),
|
||||
this.motor.pinThree.toString(),
|
||||
this.motor.pinFour.toString(),
|
||||
'counterClockwise',
|
||||
this.pauseIntervalTime.toString()
|
||||
]
|
||||
|
||||
console.log('start counterclockwise')
|
||||
this.moveProcess = childProcesses.spawn('python', motorProcessArguments)
|
||||
this.movementState = 'COUNTERCLOCKWISE'
|
||||
}
|
||||
|
||||
public stopMovement = () => {
|
||||
if (this.movementState === 'IDLE') return
|
||||
else {
|
||||
if (!this.moveProcess?.killed) this.moveProcess?.kill()
|
||||
console.log('start idle')
|
||||
this.movementState = 'IDLE'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MotorMover
|
||||
@ -1,69 +0,0 @@
|
||||
import express from 'express'
|
||||
import path from 'path'
|
||||
import bodyParser from 'body-parser'
|
||||
import http from 'http'
|
||||
import { Socket } from 'socket.io'
|
||||
import IEventManager from '../Interfaces/IEventManager'
|
||||
import EventManager from './EventManager'
|
||||
|
||||
class Server {
|
||||
public app = express()
|
||||
private eventManager: IEventManager
|
||||
|
||||
constructor (port: number) {
|
||||
this.createApp()
|
||||
this.setupAppOptions()
|
||||
this.setupAppRoutes()
|
||||
this.startServer(port)
|
||||
this.eventManager = new EventManager()
|
||||
}
|
||||
|
||||
createApp = () => {
|
||||
this.app.use(express.json())
|
||||
this.app.use(express.urlencoded({ extended: false }))
|
||||
this.app.use(express.static(path.join(process.cwd(), '/dist/Vision/')))
|
||||
this.app.use(bodyParser.json())
|
||||
}
|
||||
|
||||
setupAppRoutes = () => {
|
||||
this.app.use('/', (request, response, next) => {
|
||||
response.sendFile(path.join(process.cwd(), './dist/Vision/index.html'))
|
||||
})
|
||||
}
|
||||
|
||||
setupAppOptions = () => {
|
||||
this.app.use((request, response, next) => {
|
||||
response.header('Access-Control-Allow-Origin', request.headers.origin || '*')
|
||||
response.header('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,HEAD,DELETE,OPTIONS')
|
||||
response.header('Access-Control-Allow-Headers', 'Content-Type,x-requested-with')
|
||||
next()
|
||||
})
|
||||
}
|
||||
|
||||
startServer = (port: number) => {
|
||||
const webService = new http.Server(this.app)
|
||||
const socketService = require("socket.io")(webService)
|
||||
this.openSockets(socketService)
|
||||
webService.listen(port, () => {
|
||||
console.log(`Server is listening on ${port}`)
|
||||
})
|
||||
}
|
||||
|
||||
openSockets = (socketService: any) => {
|
||||
socketService.on('connection', (socket: Socket) => {
|
||||
console.log('client connected')
|
||||
|
||||
socket.on('offsets', (offsets: any[]) => {
|
||||
this.onReceiveOffsets(offsets)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public onReceiveOffsets = (offsets: any[]) => {
|
||||
this.eventManager.emit('onReceiveOffsets', offsets)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Server
|
||||
@ -1,13 +0,0 @@
|
||||
import IWaterPump from '../Interfaces/IWaterPump'
|
||||
|
||||
class WaterPump implements IWaterPump {
|
||||
public pinOne: number
|
||||
public pinTwo: number
|
||||
|
||||
constructor (props: IWaterPump) {
|
||||
this.pinOne = props.pinOne
|
||||
this.pinTwo = props.pinTwo
|
||||
}
|
||||
}
|
||||
|
||||
export default WaterPump
|
||||
@ -1,46 +0,0 @@
|
||||
import IWaterPump from '../Interfaces/IWaterPump'
|
||||
import * as childProcesses from 'child_process'
|
||||
import IWaterPumperConstructor from '../Interfaces/IWaterPumperConstructor'
|
||||
import IWaterPumper from '../Interfaces/IWaterPumper'
|
||||
import makeWaterPump from '../UseCases/Factories/makeWaterPump'
|
||||
|
||||
class WaterPumper implements IWaterPumper {
|
||||
public waterPump: IWaterPump
|
||||
public isActive: boolean = false
|
||||
private pumpProcess: childProcesses.ChildProcessWithoutNullStreams | null = null
|
||||
private pumpActiveTimeInSeconds: number
|
||||
private pumpCoolDownTimeInSeconds: number
|
||||
|
||||
constructor (props: IWaterPumperConstructor) {
|
||||
this.waterPump = makeWaterPump({
|
||||
pinOne: props.pinOne,
|
||||
pinTwo: props.pinTwo
|
||||
})
|
||||
|
||||
this.pumpActiveTimeInSeconds =props.pumpActiveTimeInSeconds
|
||||
this.pumpCoolDownTimeInSeconds = props.pumpCoolDownTimeInSeconds
|
||||
}
|
||||
|
||||
private async coolDown () {
|
||||
return new Promise(resolve => setTimeout(resolve, this.pumpCoolDownTimeInSeconds * 1000))
|
||||
}
|
||||
|
||||
public async pump () {
|
||||
if (this.isActive) return
|
||||
|
||||
const pumpProcessArguments = [
|
||||
'src/Robotics/moveDcMotor.py',
|
||||
this.waterPump.pinOne.toString(),
|
||||
this.waterPump.pinTwo.toString(),
|
||||
this.pumpActiveTimeInSeconds.toString()
|
||||
]
|
||||
|
||||
this.pumpProcess = childProcesses.spawn('python', pumpProcessArguments)
|
||||
|
||||
this.isActive = true
|
||||
await this.coolDown()
|
||||
this.isActive = false
|
||||
}
|
||||
}
|
||||
|
||||
export default WaterPumper
|
||||
@ -1,6 +0,0 @@
|
||||
interface IEventManager {
|
||||
listen(eventName: string, callback: any): void,
|
||||
emit(eventName: string, detail: any): void
|
||||
}
|
||||
|
||||
export default IEventManager
|
||||
@ -1,8 +0,0 @@
|
||||
interface IMotor {
|
||||
pinOne: number,
|
||||
pinTwo: number,
|
||||
pinThree: number,
|
||||
pinFour: number
|
||||
}
|
||||
|
||||
export default IMotor
|
||||
@ -1,8 +0,0 @@
|
||||
interface IMotorMover {
|
||||
moveClockwise(): void,
|
||||
moveCounterClockwise(): void,
|
||||
stopMovement(): void,
|
||||
movementState: 'CLOCKWISE' | 'COUNTERCLOCKWISE' | "IDLE"
|
||||
}
|
||||
|
||||
export default IMotorMover
|
||||
@ -1,8 +0,0 @@
|
||||
import IMotor from "./IMotor";
|
||||
|
||||
interface IMotorMoverConstructor {
|
||||
motor: IMotor,
|
||||
pauseIntervalTime: number
|
||||
}
|
||||
|
||||
export default IMotorMoverConstructor
|
||||
@ -1,5 +0,0 @@
|
||||
interface IServer {
|
||||
port: number
|
||||
}
|
||||
|
||||
export default IServer
|
||||
@ -1,6 +0,0 @@
|
||||
interface IWaterPump {
|
||||
pinOne: number,
|
||||
pinTwo: number
|
||||
}
|
||||
|
||||
export default IWaterPump
|
||||
@ -1,9 +0,0 @@
|
||||
import IWaterPump from "./IWaterPump";
|
||||
|
||||
interface IWaterPumper {
|
||||
pump(): void
|
||||
isActive: boolean
|
||||
waterPump: IWaterPump
|
||||
}
|
||||
|
||||
export default IWaterPumper
|
||||
@ -1,8 +0,0 @@
|
||||
interface IWaterPumperConstructor {
|
||||
pinOne: number,
|
||||
pinTwo: number,
|
||||
pumpActiveTimeInSeconds: number,
|
||||
pumpCoolDownTimeInSeconds: number
|
||||
}
|
||||
|
||||
export default IWaterPumperConstructor
|
||||
@ -1,7 +0,0 @@
|
||||
import EventManager from "../../Entities/EventManager"
|
||||
|
||||
function makeEventManager () {
|
||||
return new EventManager()
|
||||
}
|
||||
|
||||
export default makeEventManager
|
||||
@ -1,8 +0,0 @@
|
||||
import Motor from "../../Entities/Motor"
|
||||
import IMotor from "../../Interfaces/IMotor"
|
||||
|
||||
function makeMotor (props: IMotor) {
|
||||
return new Motor(props)
|
||||
}
|
||||
|
||||
export default makeMotor
|
||||
@ -1,8 +0,0 @@
|
||||
import MotorMover from "../../Entities/MotorMover"
|
||||
import IMotorMoverConstructor from "../../Interfaces/IMotorMoverConstructor"
|
||||
|
||||
function makeMotorMover (props: IMotorMoverConstructor) {
|
||||
return new MotorMover(props)
|
||||
}
|
||||
|
||||
export default makeMotorMover
|
||||
@ -1,9 +0,0 @@
|
||||
import Server from "../../Entities/Server"
|
||||
|
||||
function makeServer (port: number) {
|
||||
const defaultPort = 5005
|
||||
|
||||
return new Server(port || defaultPort)
|
||||
}
|
||||
|
||||
export default makeServer
|
||||
@ -1,8 +0,0 @@
|
||||
import WaterPump from "../../Entities/WaterPump"
|
||||
import IWaterPump from "../../Interfaces/IWaterPump"
|
||||
|
||||
function makeWaterPump (props: IWaterPump) {
|
||||
return new WaterPump(props)
|
||||
}
|
||||
|
||||
export default makeWaterPump
|
||||
@ -1,8 +0,0 @@
|
||||
import WaterPumper from "../../Entities/WaterPumper"
|
||||
import IWaterPumperConstructor from "../../Interfaces/IWaterPumperConstructor"
|
||||
|
||||
function makeWaterPumper (props: IWaterPumperConstructor) {
|
||||
return new WaterPumper(props)
|
||||
}
|
||||
|
||||
export default makeWaterPumper
|
||||
@ -1,60 +0,0 @@
|
||||
import IEventManager from './Interfaces/IEventManager'
|
||||
import IMotorMover from './Interfaces/IMotorMover'
|
||||
import IWaterPumper from './Interfaces/IWaterPumper'
|
||||
|
||||
import makeServer from './UseCases/Factories/makeServer'
|
||||
import makeEventManager from './UseCases/Factories/makeEventManager'
|
||||
import makeMotorMover from './UseCases/Factories/makeMotorMover'
|
||||
import makeWaterPumper from './UseCases/Factories/makeWaterPumper'
|
||||
|
||||
const main = () => {
|
||||
console.log('Starting Robotics')
|
||||
|
||||
const port = 5005
|
||||
makeServer(port)
|
||||
|
||||
const eventManager: IEventManager = makeEventManager()
|
||||
|
||||
const xAxisMotorMover: IMotorMover = makeMotorMover({
|
||||
motor: { pinOne: 3, pinTwo: 5, pinThree: 7, pinFour: 11 },
|
||||
pauseIntervalTime: 0.05
|
||||
})
|
||||
|
||||
const yAxisMotorMover: IMotorMover = makeMotorMover({
|
||||
motor: { pinOne: 13, pinTwo: 15, pinThree: 19, pinFour: 21 },
|
||||
pauseIntervalTime: 0.05
|
||||
})
|
||||
|
||||
const waterPumper: IWaterPumper = makeWaterPumper({
|
||||
pinOne: 37,
|
||||
pinTwo: 35,
|
||||
pumpActiveTimeInSeconds: 1,
|
||||
pumpCoolDownTimeInSeconds: 5
|
||||
})
|
||||
|
||||
eventManager.listen('onReceiveOffsets', (offsets: any[]) => {
|
||||
if (offsets[0]?.x > 50) {
|
||||
xAxisMotorMover.moveCounterClockwise()
|
||||
} else if (offsets[0]?.x < - 50) {
|
||||
xAxisMotorMover.moveClockwise()
|
||||
} else {
|
||||
xAxisMotorMover.stopMovement()
|
||||
}
|
||||
|
||||
if (offsets[0]?.y > 50) {
|
||||
yAxisMotorMover.moveClockwise()
|
||||
} else if (offsets[0]?.y < - 50) {
|
||||
yAxisMotorMover.moveCounterClockwise()
|
||||
} else {
|
||||
yAxisMotorMover.stopMovement()
|
||||
}
|
||||
|
||||
if (offsets[0]?.hypotenuse <= 80) {
|
||||
waterPumper.pump()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
export { main }
|
||||
@ -1,22 +0,0 @@
|
||||
# command arguments to run process
|
||||
# 1: int pin_one
|
||||
# 2: int pin_two
|
||||
# 3: int motor_active_time
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
from time import sleep
|
||||
import sys
|
||||
|
||||
motor_channel = (int(sys.argv[1]), int(sys.argv[2])) # (37, 35)
|
||||
|
||||
motor_active_time = int(sys.argv[3])
|
||||
|
||||
GPIO.setwarnings(True)
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
GPIO.setup(motor_channel, GPIO.OUT)
|
||||
|
||||
GPIO.output(motor_channel, (GPIO.HIGH, GPIO.LOW))
|
||||
print('Should be on')
|
||||
|
||||
sleep(motor_active_time)
|
||||
GPIO.output(motor_channel, (GPIO.LOW, GPIO.LOW))
|
||||
38
src/Server/Server.ts
Normal file
38
src/Server/Server.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import express from 'express'
|
||||
import path from 'path'
|
||||
import bodyParser from 'body-parser'
|
||||
|
||||
class Server {
|
||||
public app = express()
|
||||
|
||||
constructor () {
|
||||
this.createApp()
|
||||
this.setupAppOptions()
|
||||
this.setupAppRoutes()
|
||||
}
|
||||
|
||||
createApp = () => {
|
||||
this.app.use(express.json())
|
||||
this.app.use(express.urlencoded({ extended: false }))
|
||||
this.app.use(express.static(path.join(process.cwd(), '/build')))
|
||||
this.app.use(bodyParser.json())
|
||||
}
|
||||
|
||||
setupAppRoutes = () => {
|
||||
// this.app.use('/api', apiRouter)
|
||||
this.app.use('/', (request, response, next) => {
|
||||
response.sendFile(path.join(process.cwd(), './dist/Vision/index.html'))
|
||||
})
|
||||
}
|
||||
|
||||
setupAppOptions = () => {
|
||||
this.app.use((request, response, next) => {
|
||||
response.header('Access-Control-Allow-Origin', request.headers.origin || '*')
|
||||
response.header('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,HEAD,DELETE,OPTIONS')
|
||||
response.header('Access-Control-Allow-Headers', 'Content-Type,x-requested-with')
|
||||
next()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Server
|
||||
29
src/Server/main.ts
Normal file
29
src/Server/main.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import http from 'http'
|
||||
import Server from './Server'
|
||||
|
||||
const main = () => {
|
||||
|
||||
const port = normalizePort(process.env.PORT || '5005')
|
||||
const webService = createServer()
|
||||
|
||||
webService.listen(port, () => {
|
||||
console.log(`Server is listening on ${port}`)
|
||||
})
|
||||
}
|
||||
|
||||
const createServer = () => {
|
||||
const server = new Server()
|
||||
return http.createServer(server.app)
|
||||
}
|
||||
|
||||
const normalizePort = (portString: string) => {
|
||||
const port = parseInt(portString, 10)
|
||||
|
||||
if (isNaN(port)) return portString
|
||||
else if (port >= 0 ) return port
|
||||
else return 0
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
export { main, createServer, normalizePort }
|
||||
@ -1,7 +0,0 @@
|
||||
import IOffset from "./IOffset";
|
||||
|
||||
interface IRoboticsCommunicator {
|
||||
sendOffsets(offsets: IOffset[]): void
|
||||
}
|
||||
|
||||
export default IRoboticsCommunicator
|
||||
@ -3,7 +3,7 @@ import ObjectDetector from "../ObjectDetector"
|
||||
|
||||
const defaultPredictions = [
|
||||
(prediction: DetectedObject) => prediction.score > 0.6,
|
||||
(prediction: DetectedObject) => prediction.class === 'cat',
|
||||
(prediction: DetectedObject) => prediction.class === 'person',
|
||||
]
|
||||
|
||||
function makeObjectDetector (filterPredicates?: Function[]): ObjectDetector {
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import RoboticsCommunicator from "../RoboticsCommunicator"
|
||||
|
||||
|
||||
function makeRoboticsCommunicator () {
|
||||
return new RoboticsCommunicator()
|
||||
}
|
||||
|
||||
export default makeRoboticsCommunicator
|
||||
@ -1,16 +0,0 @@
|
||||
import * as io from 'socket.io-client'
|
||||
import IOffset from '../Interfaces/IOffset'
|
||||
|
||||
class RoboticsCommunicator {
|
||||
socket: SocketIOClient.Socket
|
||||
|
||||
constructor () {
|
||||
this.socket = io.connect()
|
||||
}
|
||||
|
||||
sendOffsets = (offsets: IOffset[]) => {
|
||||
this.socket.emit('offsets', offsets)
|
||||
}
|
||||
}
|
||||
|
||||
export default RoboticsCommunicator
|
||||
@ -1,7 +1,6 @@
|
||||
import IObjectDetector from './Interfaces/IObjectDetector'
|
||||
import IObjectLocator from './Interfaces/IObjectLocator'
|
||||
import IOffset from './Interfaces/IOffset'
|
||||
import IRoboticsCommunicator from './Interfaces/IRoboticsCommunicator'
|
||||
import IUiRenderer from './Interfaces/IUiRenderer'
|
||||
import IVideoCapturer from "./Interfaces/IVideoCapturer"
|
||||
|
||||
@ -9,20 +8,17 @@ import makeObjectDetector from './UseCases/Factories/makeObjectDetector'
|
||||
import makeObjectLocator from './UseCases/Factories/makeObjectLocator'
|
||||
import makeUiRenderer from './UseCases/Factories/makeUiRenderer'
|
||||
import makeVideoCapturer from './UseCases/Factories/makeVideoCatpurer'
|
||||
import makeRoboticsCommunicator from './UseCases/Factories/mkaeRoboticsCommunicator'
|
||||
|
||||
class App {
|
||||
private objectDetector: IObjectDetector
|
||||
private objectLocator: IObjectLocator
|
||||
private videoCapturer: IVideoCapturer
|
||||
private roboticsCommunicator: IRoboticsCommunicator
|
||||
private uiRenderer: IUiRenderer
|
||||
|
||||
constructor () {
|
||||
this.videoCapturer = makeVideoCapturer()
|
||||
this.objectDetector = makeObjectDetector()
|
||||
this.objectLocator = makeObjectLocator()
|
||||
this.roboticsCommunicator = makeRoboticsCommunicator()
|
||||
this.uiRenderer = makeUiRenderer()
|
||||
|
||||
const eventTarget = new EventTarget()
|
||||
@ -40,7 +36,6 @@ class App {
|
||||
|
||||
const predictedObjects = await this.objectDetector.getPredictionsFromImageData(imageData)
|
||||
const offsets: IOffset[] = predictedObjects.map(obj => this.objectLocator.getOffsetsFromPredictions(obj))
|
||||
this.roboticsCommunicator.sendOffsets(offsets)
|
||||
this.uiRenderer.render({ imageData, predictedObjects, offsets })
|
||||
|
||||
window.requestAnimationFrame(this.predictImage)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user