Compare commits

...

3 Commits

Author SHA1 Message Date
9d1248a27c kicad project git ignore 2025-05-12 18:08:23 +02:00
d5c8112f41 backing up old kicad project (working) 2025-05-12 18:06:25 +02:00
017b2e5a8c vue frontend 2025-05-12 18:06:19 +02:00
53 changed files with 42956 additions and 4947 deletions

View File

@ -0,0 +1,5 @@
{
"include": [
"./src/**/*"
]
}

View File

@ -8,9 +8,12 @@
"name": "webapp",
"version": "0.1.0",
"dependencies": {
"@jaames/iro": "^5.5.2",
"bootstrap": "^5.1.2",
"core-js": "^3.6.5",
"vue": "^3.0.0"
"vue": "^3.0.0",
"vue-native-websocket-vue3": "^3.1.4",
"vuex": "^4.0.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
@ -1669,6 +1672,20 @@
"webpack": "^4.0.0"
}
},
"node_modules/@irojs/iro-core": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz",
"integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A=="
},
"node_modules/@jaames/iro": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz",
"integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==",
"dependencies": {
"@irojs/iro-core": "^1.2.1",
"preact": "^10.0.0"
}
},
"node_modules/@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@ -2495,6 +2512,11 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"node_modules/@vue/devtools-api": {
"version": "6.0.0-beta.19",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz",
"integrity": "sha512-ObzQhgkoVeoyKv+e8+tB/jQBL2smtk/NmC9OmFK8UqdDpoOdv/Kf9pyDWL+IFyM7qLD2C75rszJujvGSPSpGlw=="
},
"node_modules/@vue/preload-webpack-plugin": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
@ -3269,8 +3291,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base": {
"version": "0.11.2",
@ -3480,7 +3501,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4508,8 +4528,7 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"node_modules/concat-stream": {
"version": "1.6.2",
@ -7031,8 +7050,7 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"node_modules/fsevents": {
"version": "2.3.2",
@ -7142,7 +7160,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -7959,7 +7976,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@ -7968,8 +7984,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/inquirer": {
"version": "7.3.3",
@ -9328,7 +9343,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -9941,7 +9955,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@ -10319,7 +10332,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -11155,6 +11167,15 @@
"node": ">=0.10.0"
}
},
"node_modules/preact": {
"version": "10.5.15",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz",
"integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@ -14199,6 +14220,60 @@
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
"node_modules/vue-native-websocket-vue3": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/vue-native-websocket-vue3/-/vue-native-websocket-vue3-3.1.4.tgz",
"integrity": "sha512-Dqq+LaoV1ZgWhPGIEBKBIXMc+n+7Bh6BkAgnRrf3iV6NSOA7q42dQNOEPbJCzmn/L779ck56RT1UtoCZfIwq/w==",
"dependencies": {
"file-entry-cache": "^6.0.1"
},
"peerDependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
}
},
"node_modules/vue-native-websocket-vue3/node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"dependencies": {
"flat-cache": "^3.0.4"
},
"engines": {
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/vue-native-websocket-vue3/node_modules/flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
"integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
"dependencies": {
"flatted": "^3.1.0",
"rimraf": "^3.0.2"
},
"engines": {
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/vue-native-websocket-vue3/node_modules/flatted": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA=="
},
"node_modules/vue-native-websocket-vue3/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@ -14221,6 +14296,17 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"node_modules/vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.11"
},
"peerDependencies": {
"vue": "^3.0.2"
}
},
"node_modules/watchpack": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
@ -15134,8 +15220,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"node_modules/write": {
"version": "1.0.3",
@ -16550,6 +16635,20 @@
"postcss": "^7.0.0"
}
},
"@irojs/iro-core": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz",
"integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A=="
},
"@jaames/iro": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz",
"integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==",
"requires": {
"@irojs/iro-core": "^1.2.1",
"preact": "^10.0.0"
}
},
"@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@ -17251,6 +17350,11 @@
}
}
},
"@vue/devtools-api": {
"version": "6.0.0-beta.19",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz",
"integrity": "sha512-ObzQhgkoVeoyKv+e8+tB/jQBL2smtk/NmC9OmFK8UqdDpoOdv/Kf9pyDWL+IFyM7qLD2C75rszJujvGSPSpGlw=="
},
"@vue/preload-webpack-plugin": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
@ -17891,8 +17995,7 @@
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"base": {
"version": "0.11.2",
@ -18067,7 +18170,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -18912,8 +19014,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
@ -20921,8 +21022,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.3.2",
@ -21004,7 +21104,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -21632,7 +21731,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@ -21641,8 +21739,7 @@
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"inquirer": {
"version": "7.3.3",
@ -22701,7 +22798,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -23198,7 +23294,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
@ -23504,8 +23599,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-is-inside": {
"version": "1.0.2",
@ -24223,6 +24317,11 @@
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true
},
"preact": {
"version": "10.5.15",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz",
"integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA=="
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@ -26741,6 +26840,46 @@
}
}
},
"vue-native-websocket-vue3": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/vue-native-websocket-vue3/-/vue-native-websocket-vue3-3.1.4.tgz",
"integrity": "sha512-Dqq+LaoV1ZgWhPGIEBKBIXMc+n+7Bh6BkAgnRrf3iV6NSOA7q42dQNOEPbJCzmn/L779ck56RT1UtoCZfIwq/w==",
"requires": {
"file-entry-cache": "^6.0.1"
},
"dependencies": {
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"requires": {
"flat-cache": "^3.0.4"
}
},
"flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
"integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
"requires": {
"flatted": "^3.1.0",
"rimraf": "^3.0.2"
}
},
"flatted": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA=="
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"requires": {
"glob": "^7.1.3"
}
}
}
},
"vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@ -26765,6 +26904,14 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
},
"watchpack": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
@ -27494,8 +27641,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"write": {
"version": "1.0.3",

View File

@ -8,9 +8,12 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@jaames/iro": "^5.5.2",
"bootstrap": "^5.1.2",
"core-js": "^3.6.5",
"vue": "^3.0.0"
"vue": "^3.0.0",
"vue-native-websocket-vue3": "^3.1.4",
"vuex": "^4.0.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",

View File

@ -1,17 +1,23 @@
<!DOCTYPE html>
<html lang="">
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
</head>
<body class="bg-dark text-white">
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</body>
</html>

View File

@ -1,295 +1,85 @@
<template>
<div class="bg-dark text-white">
<div class="container">
<div class="row py-4 text-center" id="header">
<h1>Tropicananass Leds</h1>
</div>
<WSConnection v-if="!this.isConnected"></WSConnection>
<Reconnect></Reconnect>
<ModeSelect mode_list="{Test, Artnet, Auto, Manual}"></ModeSelect>
<div class="row pt-2 gy-2">
<div class="col d-flex justify-content-center">
<form
id="mode-input"
class="btn-group"
role="group"
aria-label="Select mode"
>
<input
type="radio"
class="btn-check"
name="mode-selection"
id="test-mode"
autocomplete="off"
value="0"
checked
/>
<input
type="radio"
class="btn-check"
name="mode-selection"
id="artnet-mode"
autocomplete="off"
value="1"
/>
<input
type="radio"
class="btn-check"
name="mode-selection"
id="auto-mode"
autocomplete="off"
value="2"
/>
<input
type="radio"
class="btn-check"
name="mode-selection"
id="manual-mode"
autocomplete="off"
value="3"
/>
</form>
</div>
<div class="col d-flex justify-content-center">
<form
id="pattern-input"
class="btn-group"
role="group"
aria-label="Select pattern"
>
<input
type="radio"
class="btn-check"
name="pattern-selection"
id="pulse-pattern"
autocomplete="off"
value="0"
checked
/>
<input
type="radio"
class="btn-check"
name="pattern-selection"
id="travel-pattern"
autocomplete="off"
value="1"
/>
<input
type="radio"
class="btn-check"
name="pattern-selection"
id="strobe-pattern"
autocomplete="off"
value="2"
/>
</form>
<div class="row pt-2 gy-2 justify-content-evenly align-items-center">
<RadioButtonGroup
group_name="mode"
:label_list="['test', 'artnet', 'auto', 'manual']"
:checked_index="mode"
:callback="modeSelectCallback"
></RadioButtonGroup>
<AutoMode v-if="mode == 2"></AutoMode>
</div>
</div>
<div class="row pt-2 gy-2">
<legend class="col-12 col-sm-auto">Channel</legend>
<!-- <div class="col d-flex justify-content-center">
<form id="channelGlobal-input" class="btn-group" role="group" aria-label="Select channel">
<input type="radio" class="btn-check" name="channelGlobal-selection" id="all-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channelGlobal-selection" id="none-channel" autocomplete="off">
</form>
</div> -->
<div class="col d-flex justify-content-center">
<form
id="channel-input"
class="btn-group"
role="group"
aria-label="Select channel"
>
<!-- todo: Change to checkbox -->
<input
type="radio"
class="btn-check"
name="channel-selection"
id="all-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="0-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="1-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="2-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="3-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="4-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="5-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="6-channel"
autocomplete="off"
checked
/>
<input
type="radio"
class="btn-check"
name="channel-selection"
id="7-channel"
autocomplete="off"
checked
/>
</form>
</div>
</div>
<div class="row pt-2 gy-2">
<label
class="form-label col-9 col-sm-2 text-sm-end"
for="formControlRange"
>Sensitivity</label
>
<span class="col-3 col-sm-1 text-end">50</span>
<div class="col col-sm-9">
<input
type="range"
class="form-range"
id="formControlRange"
oninput="rangeCallback(this)"
/>
</div>
</div>
<div class="row pt-2 gy-2">
<label
class="form-label col-9 col-sm-2 text-sm-end"
for="formControlRange"
>Gravity</label
>
<span class="col-3 col-sm-1 text-end">50</span>
<div class="col col-sm-9">
<input
type="range"
class="form-range col-auto"
id="formControlRange"
oninput="rangeCallback(this)"
/>
</div>
</div>
<div class="row pt-2 gy-2">
<div class="col">
<div class="form-check form-switch">
<input
class="form-check-input"
type="checkbox"
id="modulateColor"
onclick="colorModulateCallback(this)"
/>
<label class="form-check-label" for="modulateColor"
>Modulate color</label
>
</div>
</div>
</div>
<div class="row pt-2 gy-2">
<div id="mainPicker" class="col d-flex justify-content-center"></div>
<div
id="modulationPicker"
class="col d-none d-flex justify-content-center"
></div>
</div>
<div class="row pt-2 gy-2">
<label
class="form-label col-9 col-sm-2 text-sm-end"
for="formControlRange"
>Modulation speed</label
>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input
type="range"
class="form-range col-auto"
id="formControlRange"
oninput="rangeCallback(this)"
/>
</div>
</div>
<div class="row pt-2 gy-2">
<label
class="form-label col-9 col-sm-2 text-sm-end"
for="formControlRange"
>Freq</label
>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input
type="range"
class="form-range col-auto"
id="formControlRange"
oninput="rangeCallback(this)"
/>
</div>
</div>
</div>
</div>
<h1>Hello !!</h1>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</template>
<script>
import Reconnect from "./components/Reconnect.vue";
import ModeSelect from "./components/ModeSelect.vue";
import RadioButtonGroup from "./components/ui/RadioButtonGroup.vue";
import AutoMode from "./components/AutoMode.vue";
import WSConnection from "./components/WSConnection.vue";
const data = {
mode: 2,
ws: null,
readyState: 0,
};
export default {
name: "App",
data() {
return data;
},
components: {
Reconnect,
ModeSelect,
RadioButtonGroup,
AutoMode,
WSConnection,
},
created() {
this.ws = new WebSocket("ws://192.168.4.1:8080");
this.ws.onopen = function (event) {
console.log(`[open] ws: Connection established: ${event.code}`);
console.log(this);
};
this.ws.onmessage = function (event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
};
this.ws.onclose = function (event) {
if (event.wasClean) {
console.log(
`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`
);
} else {
console.log("[close] ws: Connection died");
}
};
this.ws.onerror = function (error) {
console.log(`[error] ws: ${error.message}`);
};
},
computed: {
isConnected() {
return this.readyState == WebSocket.OPEN;
},
},
methods: {
modeSelectCallback: function (event) {
if (event.target.nodeName == "INPUT") {
this.mode = Number(event.target.value);
console.log("m:" + this.mode);
}
},
},
};
</script>
<style></style>
<style scoped>
.row {
margin: 0;
padding: 0;
}
</style>

View File

@ -0,0 +1,67 @@
<template>
<RadioButtonGroup
group_name="pattern"
:label_list="['pulse', 'travel', 'strobe']"
:checked_index="pattern"
:callback="patternSelectCallback"
></RadioButtonGroup>
<div class="w-100 d-block d-lg-none"></div>
<RadioButtonGroup
group_name="channel"
:label_list="['0', '1', '2', '3', '4', '5', '6', '7', 'all']"
:checked_index="channel"
:callback="channelSelectCallback"
>
channels
</RadioButtonGroup>
<PulsePattern v-if="pattern == 0"></PulsePattern>
<TravelPattern v-else-if="pattern == 1"></TravelPattern>
<StrobePattern v-else-if="pattern == 2"></StrobePattern>
</template>
<script>
import RadioButtonGroup from "./ui/RadioButtonGroup.vue";
import PulsePattern from "./patterns/Pulse.vue";
import StrobePattern from "./patterns/Strobe.vue";
import TravelPattern from "./patterns/Travel.vue";
const data = {
pattern: 1,
channel: 8,
};
export default {
name: "AutoMode",
components: {
RadioButtonGroup,
PulsePattern,
TravelPattern,
StrobePattern,
},
data() {
return data;
},
methods: {
patternSelectCallback: function (event) {
if (event.target.nodeName == "INPUT") {
this.pattern = Number(event.target.value);
console.log("p:" + this.pattern);
}
},
channelSelectCallback: function (event) {
if (event.target.nodeName == "INPUT") {
let selectedChannel = event.target.id.split("-")[0];
if (selectedChannel == "all") {
this.channel = 8;
} else {
this.channel = Number(selectedChannel);
}
console.log("c:" + this.channel);
}
},
},
};
</script>

View File

@ -1,34 +0,0 @@
<template>
<div class="row pt-2 gy-2">
<div class="col d-flex justify-content-center">
<form id="mode-input" class="btn-group" role="group" aria-label="Select mode">
<input type="radio" class="btn-check" name="mode-selection" id="test-mode" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="mode-selection" id="artnet-mode" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="mode-selection" id="auto-mode" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="mode-selection" id="manual-mode" autocomplete="off" value="3">
</form>
</div>
<div class="col d-flex justify-content-center">
<form id="pattern-input" class="btn-group" role="group" aria-label="Select pattern">
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern" autocomplete="off" value="2">
</form>
</div>
</div>
</template>
<script>
export default {
name: 'Reconnect',
props: {
msg: String
}
}
</script>
<style scoped>
#reconnectBackdrop{
visibility: hidden;
}
</style>

View File

@ -1,34 +0,0 @@
<template>
<div class="row pt-2 gy-2">
<div class="col d-flex justify-content-center">
<form id="mode-input" class="btn-group" role="group" aria-label="Select mode">
<div v-for="modename in mode_list" v-bind:key="modename">
<input :id="modename" type="radio" class="btn-check" name="mode-selection" autocomplete="off" value="0" checked>
</div>
</form>
</div>
<div class="col d-flex justify-content-center">
<form id="pattern-input" class="btn-group" role="group" aria-label="Select pattern">
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern" autocomplete="off" value="2">
</form>
</div>
</div>
</template>
<script>
export default {
name: 'ModeSelect',
props: {
mode_list: Array,
callback_list: Array
}
}
</script>
<style scoped>
#reconnectBackdrop{
visibility: hidden;
}
</style>

View File

@ -1,33 +0,0 @@
<template>
<div class="modal fade text-black" id="reconnectBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="connectionLostLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="connectionLostLabel">Connection lost</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Try reconnecting in <span id="time-left">60s</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="{timeout=1;}">Reconnect now</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Reconnect',
props: {
msg: String
}
}
</script>
<style scoped>
#reconnectBackdrop{
visibility: hidden;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<div
class="modal fade text-black show"
id="reconnectBackdrop"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabindex="-1"
aria-labelledby="connectionLostLabel"
aria-hidden="true"
ref="reconnectBackdrop"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="connectionLostLabel">Connection lost</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
{{ isConnected }} <span id="time-left">60s</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" @click="reconnect">
Reconnect now
</button>
<button type="button" class="btn btn-primary">
{{ isConnected }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
const data = {};
export default {
name: "WSConnection",
data() {
return data;
},
props: { isConnected: Boolean },
created() {},
methods: {
log() {
console.log(this.socket);
},
},
};
</script>
<style scoped>
#reconnectBackdrop {
display: block;
}
</style>

View File

@ -0,0 +1,34 @@
<template>
<div class="row pt-2 px-0 gy-2 justify-content-center">
<div class="col-12 col-md">
<RangeSlider class="col" v-model:value="sensitivity">
sensitivity
</RangeSlider>
</div>
<div class="col-12 col-md">
<RangeSlider v-model:value="gravity"> gravity </RangeSlider>
</div>
</div>
</template>
<script>
import RangeSlider from "../ui/RangeSlider.vue";
export default {
name: "Pulse",
components: {
RangeSlider,
},
data() {
return { sensitivity: 70, gravity: 50 };
},
methods: {
sliderCallback: function (event) {
if (event.target.nodeName == "INPUT") {
console.log(event.target.id + ":" + this.channel);
}
},
},
};
</script>

View File

@ -0,0 +1,29 @@
<template>
<div class="row pt-2 px-0 gy-2 justify-content-center">
<div class="col-12 col-md">
<RangeSlider class="col" v-model:value="speed"> speed </RangeSlider>
</div>
</div>
</template>
<script>
import RangeSlider from "../ui/RangeSlider.vue";
export default {
name: "Strobe",
components: {
RangeSlider,
},
data() {
return { speed: 50 };
},
methods: {
sliderCallback: function (event) {
if (event.target.nodeName == "INPUT") {
console.log(event.target.id + ":" + this.channel);
}
},
},
};
</script>

View File

@ -0,0 +1,53 @@
<template>
<div class="row pt-2 px-0 gy-2 justify-content-center">
<div class="col-12 col-md">
<RangeSlider class="col" v-model:value="sensitivity">
sensitivity
</RangeSlider>
</div>
<div class="col-12 col-md">
<RangeSlider v-model:value="gravity"> gravity </RangeSlider>
</div>
</div>
<ColorAndModulation
:colorCallback="colorCallback"
:modulationCallback="modulationCallback"
ref="color_and_modulation"
></ColorAndModulation>
</template>
<script>
import ColorAndModulation from "../ui/ColorAndModulation.vue";
import RangeSlider from "../ui/RangeSlider.vue";
const data = {
sensitivity: 33,
gravity: 88,
};
export default {
name: "Travel",
components: {
ColorAndModulation,
RangeSlider,
},
data() {
return data;
},
methods: {
sliderCallback: function (event) {
if (event.target.nodeName == "INPUT") {
console.log(event.target.id + ":" + event.target.value);
}
},
colorCallback: function (color) {
console.log(color.hsv);
console.log(color.hsl);
},
modulationCallback: function (modulation) {
console.log(modulation);
},
},
};
</script>

View File

@ -0,0 +1,27 @@
<template>
<div class="form-check form-switch">
<input
class="form-check-input"
type="checkbox"
id="label"
:checked="is_checked"
@click="$emit('update:is_checked', !is_checked)"
/>
<label class="form-check-label text-capitalize" for="label">
{{ label }}
</label>
</div>
</template>
<script>
export default {
name: "CheckBox",
props: {
is_checked: Boolean,
},
setup(props, { slots }) {
const label = slots.default()[0].children.replace(/([A-Z_-])/g, " $1");
return { label };
},
};
</script>

View File

@ -0,0 +1,71 @@
<template>
<div class="row pt-2 gy-2 justify-content-center">
<div class="col-auto">
<CheckBox label="modulateColor" v-model:is_checked="modulateColor">
modulateColor
</CheckBox>
</div>
<div v-if="modulateColor" class="col-12 col-md">
<RangeSlider v-model:value="modulationSpeed">
modulation Speed
</RangeSlider>
</div>
<div v-if="modulateColor" class="w-100 d-block d-xxl-none"></div>
<div v-else class="w-100 d-block d-sm-none"></div>
<div class="col">
<ColorPicker
name="mainPicker"
:color_array="[color_array[0], color_array[1]]"
:callback="colorCallback"
></ColorPicker>
</div>
<div v-if="modulateColor" class="col">
<ColorPicker
name="modulationPicker"
:color_array="[color_array[2]]"
:callback="modulationCallback"
></ColorPicker>
</div>
</div>
</template>
<script>
import CheckBox from "./CheckBox.vue";
import ColorPicker from "./ColorPicker.vue";
import RangeSlider from "./RangeSlider.vue";
const data = {
modulateColor: true,
modulationSpeed: 50,
};
export default {
name: "ColorAndModulation",
props: {
color_array: {
type: Array,
default: function () {
return [
{ h: 180, s: 100, v: 50 },
{ h: 0, s: 80, v: 50 },
{ h: 60, s: 80, v: 50 },
];
},
},
colorCallback: { type: Function, required: true },
modulationCallback: { type: Function, required: true },
},
components: {
CheckBox,
ColorPicker,
RangeSlider,
},
data() {
return data;
},
};
</script>

View File

@ -0,0 +1,58 @@
<template>
<div :id="name" class="col d-flex justify-content-center overflow-auto"></div>
</template>
<script>
import iro from "@jaames/iro";
export default {
name: "ColorPicker",
props: {
name: String,
color_array: {
type: Array,
default: function () {
return [
{ h: 180, s: 100, v: 50 },
{ h: 0, s: 50, v: 50 },
];
},
},
callback: Function,
},
mounted() {
new iro.ColorPicker("#" + this.name, {
colors: this.color_array,
layout: [
{
component: iro.ui.Wheel,
options: {
wheelLightness: false,
},
},
{
component: iro.ui.Slider,
options: {
sliderType: "value",
},
},
],
layoutDirection: "horizontal",
width: 250,
margin: 0,
handleRadius: 14,
}).on("color:change", this.callback);
},
};
</script>
<style>
.IroColorPicker {
white-space: nowrap;
width: max-content;
}
.IroColorPicker > .IroWheel {
margin-right: 12px;
}
</style>

View File

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,29 @@
<template>
<input
:id="id"
type="radio"
class="btn-check"
:name="group_label"
autocomplete="off"
:value="value"
:checked="is_checked"
/>
<label :for="id" class="btn btn-outline-primary text-capitalize">
<slot></slot>
</label>
</template>
<script>
export default {
name: "RadioButton",
props: {
group_label: String,
value: Number,
is_checked: Boolean,
},
setup(props, { slots }) {
const id = slots.default()[0].children + "-" + props.group_label;
return { id };
},
};
</script>

View File

@ -0,0 +1,44 @@
<template>
<legend v-if="$slots.default" class="col-auto text-capitalize fs-6 mb-0">
<slot></slot>
</legend>
<div class="col-auto">
<form
:id="group_name + '-input'"
class="btn-group"
role="group"
:aria-label="'Select' + group_name"
@click="callback"
>
<RadioButton
v-for="(label, index) in label_list"
:key="index"
:group_label="group_name"
:value="index"
:is_checked="index == checked_index"
>
{{ label }}
</RadioButton>
</form>
</div>
</template>
<script>
import RadioButton from "./RadioButton.vue";
export default {
name: "ModeSelect",
props: {
group_name: String,
label_list: Array,
checked_index: {
type: Number,
default: 0,
},
callback: Function,
},
components: {
RadioButton,
},
};
</script>

View File

@ -0,0 +1,41 @@
<template>
<div class="row">
<label
class="form-label col-9 col-sm-3 text-sm-end text-capitalize pr-1"
:for="id"
>
<slot></slot>
</label>
<span class="col-3 col-sm-1 text-end"> {{ value }} </span>
<div class="col">
<input
type="range"
class="form-range"
:id="id"
@input="sliderCallback"
:value="value"
/>
</div>
</div>
</template>
<script>
export default {
name: "RangeSlider",
props: {
value: Number,
},
methods: {
sliderCallback: function (event) {
if (event.target.nodeName == "INPUT") {
this.$emit("update:value", Number(event.target.value));
console.log("s:" + this.value);
}
},
},
setup(props, { slots }) {
const id = slots.default()[0].children + "-controlRange";
return { id };
},
};
</script>

View File

@ -1,6 +1,86 @@
import { createApp } from 'vue'
import App from './App.vue'
// import store from './store'
// import store from './storews'
// import VueNativeSock from "vue-native-websocket-vue3";
import "bootstrap/dist/css/bootstrap.min.css"
import "bootstrap"
// import { createStore } from "vuex";
createApp(App).mount('#app')
const app = createApp(App)
// const store = createStore({
// state: {
// socket: {
// // Connection Status
// isConnected: false,
// // Message content
// message: "",
// // Reconnect error
// reconnectError: false,
// // Heartbeat message sending time
// heartBeatInterval: 50000,
// // Heartbeat timer
// heartBeatTimer: 0
// }
// },
// mutations: {
// // Connection open
// SOCKET_ONOPEN(state, event) {
// console.log(event);
// app.config.globalProperties.$socket = event.currentTarget;
// state.socket.isConnected = true;
// // When the connection is successful, start sending heartbeat messages regularly to avoid being disconnected by the server
// // state.socket.heartBeatTimer = setInterval(() => {
// // const message = "Heartbeat message";
// // state.socket.isConnected &&
// // app.config.globalProperties.$socket.sendObj({
// // code: 200,
// // msg: message
// // });
// // }, state.socket.heartBeatInterval);
// },
// // Connection closed
// SOCKET_ONCLOSE(state, event) {
// state.socket.isConnected = false;
// // Stop the heartbeat message when the connection is closed
// clearInterval(state.socket.heartBeatTimer);
// state.socket.heartBeatTimer = 0;
// console.log("The line is disconnected: " + new Date());
// console.log(event);
// },
// // An error occurred
// SOCKET_ONERROR(state, event) {
// console.error(state, event);
// },
// // Receive the message sent by the server
// SOCKET_ONMESSAGE(state, message) {
// state.socket.message = message;
// },
// // Auto reconnect
// SOCKET_RECONNECT(state, count) {
// console.info("消息系统重连中...", state, count);
// },
// // Reconnect error
// SOCKET_RECONNECT_ERROR(state) {
// state.socket.reconnectError = true;
// }
// },
// modules: {}
// })
// app.use(store)
// app.use(VueNativeSock, "ws://192.168.4.1:8080", {
// store: store
// }, {
// reconnection: true, // (Boolean) whether to reconnect automatically (false)
// reconnectionAttempts: 90, // (Number) number of reconnection attempts before giving up (Infinity),
// reconnectionDelay: 10, // (Number) how long to initially wait before attempting a new (1000)
// });
app.mount('#app')
export default app

View File

@ -0,0 +1,100 @@
// import Vue from 'vue'
// import Vuex from 'vuex'
import { createStore } from "vuex";
// Vue.use(Vuex)
// root state object.
// each Vuex instance is just a single state tree.
const state = {
count: 0,
webSocket: WebSocket
}
// mutations are operations that actually mutate the state.
// each mutation handler gets the entire state tree as the
// first argument, followed by additional payload arguments.
// mutations must be synchronous and can be recorded by plugins
// for debugging purposes.
const mutations = {
increment(state) {
state.count++
},
decrement(state) {
state.count--
},
reconnect() {
state.webSocket = new WebSocket("ws://tropicananass.ovh:8080");
state.webSocket.onopen = function (event) {
console.log(`[open] ws: Connection established: ${event.code}`);
};
state.webSocket.onmessage = function (event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
let message = event.data.split(":");
let command = message[0];
let payload = message[1];
console.log(command + ", " + payload);
switch (command) {
case 'm':
document.getElementById("mode-input").elements["mode-selection"][payload].checked = true;
break;
default:
break;
}
};
state.webSocket.webSocketonclose = function (event) {
if (event.wasClean) {
console.log(`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
console.log('[close] ws: Connection died');
}
};
state.webSocket.onerror = function (error) {
console.log(`[error] ws: ${error.message}`);
};
}
}
// actions are functions that cause side effects and can involve
// asynchronous operations.
const actions = {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement'),
incrementIfOdd({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('increment')
}
},
incrementAsync({ commit }) {
return new Promise((resolve) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
}
}
// getters are functions.
const getters = {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd',
isConnected: state => state.webSocket.readyState == WebSocket.OPEN
}
// A Vuex instance is created by combining the state, mutations, actions,
// and getters.
const store = createStore({
state,
getters,
actions,
mutations
})
export default store

View File

@ -0,0 +1,64 @@
import { createStore } from "vuex";
// import app from "main.js";
import { getCurrentInstance } from 'vue'
export default createStore({
state: {
socket: {
// Connection Status
isConnected: false,
// Message content
message: "",
// Reconnect error
reconnectError: false,
// Heartbeat message sending time
heartBeatInterval: 50000,
// Heartbeat timer
heartBeatTimer: 0
}
},
mutations: {
// Connection open
SOCKET_ONOPEN(state, event) {
console.log(event);
const app = getCurrentInstance()
app.config.globalProperties.$socket = event.currentTarget;
state.socket.isConnected = true;
// When the connection is successful, start sending heartbeat messages regularly to avoid being disconnected by the server
// state.socket.heartBeatTimer = setInterval(() => {
// const message = "Heartbeat message";
// state.socket.isConnected &&
// app.config.globalProperties.$socket.sendObj({
// code: 200,
// msg: message
// });
// }, state.socket.heartBeatInterval);
},
// Connection closed
SOCKET_ONCLOSE(state, event) {
state.socket.isConnected = false;
// Stop the heartbeat message when the connection is closed
clearInterval(state.socket.heartBeatTimer);
state.socket.heartBeatTimer = 0;
console.log("The line is disconnected: " + new Date());
console.log(event);
},
// An error occurred
SOCKET_ONERROR(state, event) {
console.error(state, event);
},
// Receive the message sent by the server
SOCKET_ONMESSAGE(state, message) {
state.socket.message = message;
},
// Auto reconnect
SOCKET_RECONNECT(state, count) {
console.info("消息系统重连中...", state, count);
},
// Reconnect error
SOCKET_RECONNECT_ERROR(state) {
state.socket.reconnectError = true;
}
},
modules: {}
});

View File

@ -0,0 +1,46 @@
const reconnect = function (options) {
console.log("connecting")
options.webSocket = new WebSocket("ws://192.168.4.1:8080");
options.webSocket.onopen = function (event) {
options.isConnected = true;
console.log(`[open] ws: Connection established: ${event.code}`);
};
options.webSocket.onmessage = function (event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
};
options.webSocket.onclose = function (event) {
if (event.wasClean) {
console.log(
`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`
);
} else {
console.log("[close] ws: Connection died");
}
options.isConnected = false;
};
options.webSocket.onerror = function (error) {
console.log(`[error] ws: ${error.message}`);
};
}
// const isConnected = function () {
// if (this.webSocket != null) {
// console.log(this.webSocket.readyState)
// return this.webSocket.readyState == WebSocket.OPEN
// }
// return false
// }
import { ref } from "vue"
// plugins/i18n.js
export default {
install: (app, options) => {
let webSocket = null;
app.config.globalProperties.webSocket = webSocket
app.config.globalProperties.reconnect = () => reconnect(options)
app.provide('ws', options)
app.provide('isConnected', ref(options.isConnected))
}
}

View File

@ -0,0 +1,14 @@
{
"folders": [
{
"path": "webapp"
},
{
"path": "vuex"
},
{
"path": "web"
}
],
"settings": {}
}

31
RpiLedBars/hw/.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
# For PCBs designed using KiCad: https://www.kicad.org/
# Format documentation: https://kicad.org/help/file-formats/
# Temporary files
*.000
*.bak
*.bck
*.kicad_pcb-bak
*.kicad_sch-bak
*-backups
*.kicad_prl
*.sch-bak
*~
_autosave-*
*.tmp
*-save.pro
*-save.kicad_pcb
fp-info-cache
~*.lck
\#auto_saved_files#
# Netlist files (exported from Eeschema)
*.net
# Autorouter files (exported from Pcbnew)
*.dsn
*.ses
# Exported BOM files
*.xml
*.csv

View File

@ -1,4 +0,0 @@
(sym_lib_table
(lib (name 74hct245)(type Legacy)(uri ${KIPRJMOD}/LedBarsHat.symbols/74hct245.lib)(options "")(descr ""))
(lib (name LedBarsHat-rescue)(type Legacy)(uri ${KIPRJMOD}/LedBarsHat-rescue.lib)(options "")(descr ""))
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": false,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36,
39,
40
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "LedBarsHat.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -0,0 +1,815 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"filename": "board_design_settings.json",
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.2,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.4,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "LedBarsHat.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": [
{
"netclass": "Default",
"pattern": "+12V"
},
{
"netclass": "Default",
"pattern": "+3V3"
},
{
"netclass": "Default",
"pattern": "+5V"
},
{
"netclass": "Default",
"pattern": "/I2S_CLK"
},
{
"netclass": "Default",
"pattern": "/I2S_SD"
},
{
"netclass": "Default",
"pattern": "/I2S_WS"
},
{
"netclass": "Default",
"pattern": "/SEL_MODE0"
},
{
"netclass": "Default",
"pattern": "/SEL_MODE1"
},
{
"netclass": "Default",
"pattern": "/SEL_MODE2"
},
{
"netclass": "Default",
"pattern": "/SEL_MODE3"
},
{
"netclass": "Default",
"pattern": "/SMI_SD0"
},
{
"netclass": "Default",
"pattern": "/SMI_SD1"
},
{
"netclass": "Default",
"pattern": "/SMI_SD13"
},
{
"netclass": "Default",
"pattern": "/SMI_SD14"
},
{
"netclass": "Default",
"pattern": "/SMI_SD15"
},
{
"netclass": "Default",
"pattern": "/SMI_SD16"
},
{
"netclass": "Default",
"pattern": "/SMI_SD17"
},
{
"netclass": "Default",
"pattern": "/SMI_SD2"
},
{
"netclass": "Default",
"pattern": "/SMI_SD3"
},
{
"netclass": "Default",
"pattern": "/SMI_SD4"
},
{
"netclass": "Default",
"pattern": "/SMI_SD5"
},
{
"netclass": "Default",
"pattern": "/SMI_SD6"
},
{
"netclass": "Default",
"pattern": "/SMI_SD7"
},
{
"netclass": "Default",
"pattern": "/SMI_SD8"
},
{
"netclass": "Default",
"pattern": "/SMI_SD9"
},
{
"netclass": "Default",
"pattern": "GND"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad13)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad26)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad27)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad28)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad3)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad5)"
},
{
"netclass": "Default",
"pattern": "Net-(J1-Pad7)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad1)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad2)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad3)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad4)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad5)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad6)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad7)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT1-Pad8)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad1)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad2)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad3)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad4)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad5)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad6)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad7)"
},
{
"netclass": "Default",
"pattern": "Net-(J_OUT2-Pad8)"
},
{
"netclass": "Default",
"pattern": "Net-(OUT_5V1-Pad2)"
},
{
"netclass": "Default",
"pattern": "Net-(OUT_5V1-Pad3)"
},
{
"netclass": "Default",
"pattern": "Net-(OUT_5V1-Pad5)"
},
{
"netclass": "Default",
"pattern": "Net-(R1-Pad1)"
},
{
"netclass": "Default",
"pattern": "Net-(R2-Pad2)"
},
{
"netclass": "Default",
"pattern": "Net-(R3-Pad1)"
},
{
"netclass": "Default",
"pattern": "Net-(U1-Pad9)"
},
{
"netclass": "Default",
"pattern": "VCC"
}
]
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.25,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 0.0,
"text_offset_ratio": 0.08
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "Pcbnew",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"aba859fc-9301-4741-846d-2fb5d7891b38",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,5 @@
(sym_lib_table
(version 7)
(lib (name "74hct245")(type "Legacy")(uri "${KIPRJMOD}/LedBarsHat.symbols/74hct245.lib")(options "")(descr ""))
(lib (name "LedBarsHat-rescue")(type "KiCad")(uri "${KIPRJMOD}/LedBarsHat-rescue.kicad_sym")(options "")(descr ""))
)