mirror of
https://github.com/EyeTrackVR/EyeTrackVR-Docs.git
synced 2025-09-26 23:09:15 +08:00
docs: update part list tables, move out of beta
This commit is contained in:
parent
7ed813f90d
commit
5c92fecfc4
@ -46,7 +46,7 @@ const theme = {
|
||||
text: "How to Build",
|
||||
collapsible: true,
|
||||
items: [
|
||||
{ text: "Parts List (BETA)", link: "/how_to_build/part_list" },
|
||||
{ text: "Parts List", link: "/how_to_build/part_list" },
|
||||
{
|
||||
text: "Preparing Cameras",
|
||||
link: "/how_to_build/preparing_cameras"
|
||||
|
@ -12,15 +12,20 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="component in components" :key="component.name">
|
||||
<tr v-for="(component, index) in components" :key="component.name">
|
||||
<th class="component-col">{{ component.name }}</th>
|
||||
<td class="choice-col">
|
||||
<div v-if="component.choices.length > 1" class="custom-select" @click="toggleDropdown(component)">
|
||||
<div class="selected-option">{{ component.choices[component.selectedChoice].name }}</div>
|
||||
<div v-if="component.isOpen" class="options">
|
||||
<div v-for="(choice, index) in component.choices"
|
||||
:key="index"
|
||||
@click="selectOption(component, index)"
|
||||
<div v-if="component.choices.length > 1" class="custom-select" @click="toggleDropdown(component, index)" :ref="`select-${component.name}`">
|
||||
<div class="selected-option">
|
||||
{{ component.choices[component.selectedChoice].name }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="dropdown-arrow" :class="{ 'rotate': component.isOpen }">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-if="component.isOpen" class="options" :class="{ 'options-above': isOptionsAbove(index) }">
|
||||
<div v-for="(choice, choiceIndex) in component.choices"
|
||||
:key="choiceIndex"
|
||||
@click="selectOption(component, choiceIndex)"
|
||||
class="option">
|
||||
{{ choice.name }}
|
||||
</div>
|
||||
@ -36,11 +41,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Total: ${{ total.toFixed(2) }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
data() {
|
||||
return {
|
||||
tracker: 2,
|
||||
components: [
|
||||
@ -218,13 +224,11 @@ export default {
|
||||
selectedChoice: 0,
|
||||
isOpen: false
|
||||
},
|
||||
|
||||
// Add other components similarly
|
||||
],
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
methods: {
|
||||
updatePrices() {
|
||||
let total = 0;
|
||||
this.components.forEach(component => {
|
||||
@ -237,54 +241,42 @@ export default {
|
||||
});
|
||||
this.total = total;
|
||||
},
|
||||
toggleDropdown(component) {
|
||||
// Close all other dropdowns
|
||||
toggleDropdown(component, index) {
|
||||
this.components.forEach(comp => {
|
||||
if (comp !== component) {
|
||||
comp.isOpen = false;
|
||||
}
|
||||
});
|
||||
// Toggle the clicked dropdown
|
||||
component.isOpen = !component.isOpen;
|
||||
},
|
||||
isOptionsAbove(component) {
|
||||
if (this.$refs[`select-${component.name}`]) {
|
||||
const rect = this.$refs[`select-${component.name}`].getBoundingClientRect();
|
||||
const spaceBelow = window.innerHeight - rect.bottom;
|
||||
return spaceBelow < 200 && rect.top > 200;
|
||||
}
|
||||
return false;
|
||||
isOptionsAbove(index) {
|
||||
return index >= this.components.length - 2;
|
||||
},
|
||||
selectOption(component, index) {
|
||||
component.selectedChoice = index;
|
||||
component.isOpen = false; // This line closes the dropdown
|
||||
component.isOpen = false;
|
||||
this.updatePrices();
|
||||
},
|
||||
closeAllDropdowns() {
|
||||
this.components.forEach(component => {
|
||||
component.isOpen = false;
|
||||
});
|
||||
},
|
||||
// Add this new method
|
||||
handleOutsideClick(event) {
|
||||
if (!event.target.closest('.custom-select')) {
|
||||
this.closeAllDropdowns();
|
||||
component.isOpen = false;
|
||||
});
|
||||
},
|
||||
handleOutsideClick(event) {
|
||||
if (!event.target.closest('.custom-select')) {
|
||||
this.closeAllDropdowns();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updatePrices();
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.updatePrices();
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
width: 100%;
|
||||
@ -312,34 +304,82 @@ th, td {
|
||||
.cost-all-col { width: 13%; }
|
||||
.links-col { width: 30%; }
|
||||
|
||||
.multi-line-select {
|
||||
.custom-select {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
.custom-select:hover,
|
||||
.custom-select:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.selected-option {
|
||||
border: 1px solid #999;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
height: auto;
|
||||
background-color: #666;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
text-align-last: center;
|
||||
color: #fff;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* This targets Webkit browsers like Chrome and Safari */
|
||||
select option {
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
.selected-option:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
/* This targets Firefox */
|
||||
select:-moz-focusring {
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #000;
|
||||
.options {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #222;
|
||||
border: 1px solid #444;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.options-above {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
|
||||
.option {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #444;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dropdown-arrow.rotate {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.custom-select[aria-expanded="true"] .dropdown-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@ -359,79 +399,4 @@ select:-moz-focusring {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-select {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.custom-select:hover,
|
||||
.custom-select:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.selected-option {
|
||||
border: 1px solid #444;
|
||||
padding: 5px;
|
||||
background-color: #333;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color: #545454;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #222;
|
||||
border: 1px solid #444;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
top: 100%;
|
||||
}
|
||||
.options-above {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
.option {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #444;
|
||||
color: #545454;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
/* Ensure text is visible in all states */
|
||||
.custom-select, .selected-option, .option {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Add some contrast to the selected option */
|
||||
.selected-option {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
/* Improve visibility of options */
|
||||
.options {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
/* Add a subtle hover effect */
|
||||
.option:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
</style>
|
@ -12,15 +12,20 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="component in components" :key="component.name">
|
||||
<tr v-for="(component, index) in components" :key="component.name">
|
||||
<th class="component-col">{{ component.name }}</th>
|
||||
<td class="choice-col">
|
||||
<div v-if="component.choices.length > 1" class="custom-select" @click="toggleDropdown(component)">
|
||||
<div class="selected-option">{{ component.choices[component.selectedChoice].name }}</div>
|
||||
<div v-if="component.isOpen" class="options">
|
||||
<div v-for="(choice, index) in component.choices"
|
||||
:key="index"
|
||||
@click="selectOption(component, index)"
|
||||
<div v-if="component.choices.length > 1" class="custom-select" @click="toggleDropdown(component, index)" :ref="`select-${component.name}`">
|
||||
<div class="selected-option">
|
||||
{{ component.choices[component.selectedChoice].name }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="dropdown-arrow" :class="{ 'rotate': component.isOpen }">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-if="component.isOpen" class="options" :class="{ 'options-above': isOptionsAbove(index) }">
|
||||
<div v-for="(choice, choiceIndex) in component.choices"
|
||||
:key="choiceIndex"
|
||||
@click="selectOption(component, choiceIndex)"
|
||||
class="option">
|
||||
{{ choice.name }}
|
||||
</div>
|
||||
@ -36,14 +41,15 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Total: ${{ total.toFixed(2) }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
data() {
|
||||
return {
|
||||
tracker: 2,
|
||||
components: [
|
||||
components: [
|
||||
{
|
||||
name: 'Type A USB Breakout',
|
||||
choices: [
|
||||
@ -313,12 +319,11 @@ export default {
|
||||
selectedChoice: 0,
|
||||
isOpen: false
|
||||
},
|
||||
// Add other components similarly
|
||||
],
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
methods: {
|
||||
updatePrices() {
|
||||
let total = 0;
|
||||
this.components.forEach(component => {
|
||||
@ -331,54 +336,42 @@ export default {
|
||||
});
|
||||
this.total = total;
|
||||
},
|
||||
toggleDropdown(component) {
|
||||
// Close all other dropdowns
|
||||
toggleDropdown(component, index) {
|
||||
this.components.forEach(comp => {
|
||||
if (comp !== component) {
|
||||
comp.isOpen = false;
|
||||
}
|
||||
});
|
||||
// Toggle the clicked dropdown
|
||||
component.isOpen = !component.isOpen;
|
||||
},
|
||||
isOptionsAbove(component) {
|
||||
if (this.$refs[`select-${component.name}`]) {
|
||||
const rect = this.$refs[`select-${component.name}`].getBoundingClientRect();
|
||||
const spaceBelow = window.innerHeight - rect.bottom;
|
||||
return spaceBelow < 200 && rect.top > 200;
|
||||
}
|
||||
return false;
|
||||
isOptionsAbove(index) {
|
||||
return index >= this.components.length - 2;
|
||||
},
|
||||
selectOption(component, index) {
|
||||
component.selectedChoice = index;
|
||||
component.isOpen = false; // This line closes the dropdown
|
||||
component.isOpen = false;
|
||||
this.updatePrices();
|
||||
},
|
||||
closeAllDropdowns() {
|
||||
this.components.forEach(component => {
|
||||
component.isOpen = false;
|
||||
});
|
||||
},
|
||||
// Add this new method
|
||||
handleOutsideClick(event) {
|
||||
if (!event.target.closest('.custom-select')) {
|
||||
this.closeAllDropdowns();
|
||||
component.isOpen = false;
|
||||
});
|
||||
},
|
||||
handleOutsideClick(event) {
|
||||
if (!event.target.closest('.custom-select')) {
|
||||
this.closeAllDropdowns();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updatePrices();
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.updatePrices();
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
width: 100%;
|
||||
@ -406,34 +399,82 @@ th, td {
|
||||
.cost-all-col { width: 13%; }
|
||||
.links-col { width: 30%; }
|
||||
|
||||
.multi-line-select {
|
||||
.custom-select {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
.custom-select:hover,
|
||||
.custom-select:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.selected-option {
|
||||
border: 1px solid #999;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
height: auto;
|
||||
background-color: #666;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
text-align-last: center;
|
||||
color: #fff;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* This targets Webkit browsers like Chrome and Safari */
|
||||
select option {
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
.selected-option:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
/* This targets Firefox */
|
||||
select:-moz-focusring {
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #000;
|
||||
.options {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #222;
|
||||
border: 1px solid #444;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.options-above {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
|
||||
.option {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #444;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dropdown-arrow.rotate {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.custom-select[aria-expanded="true"] .dropdown-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@ -453,79 +494,4 @@ select:-moz-focusring {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-select {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.custom-select:hover,
|
||||
.custom-select:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.selected-option {
|
||||
border: 1px solid #444;
|
||||
padding: 5px;
|
||||
background-color: #333;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color: #545454;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #222;
|
||||
border: 1px solid #444;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
top: 100%;
|
||||
}
|
||||
.options-above {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
}
|
||||
.option {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #444;
|
||||
color: #545454;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
/* Ensure text is visible in all states */
|
||||
.custom-select, .selected-option, .option {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Add some contrast to the selected option */
|
||||
.selected-option {
|
||||
background-color: #1e1e20;
|
||||
}
|
||||
|
||||
/* Improve visibility of options */
|
||||
.options {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
/* Add a subtle hover effect */
|
||||
.option:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
</style>
|
@ -24,28 +24,7 @@ There are two primary categories of trackers supported: wireless and wired.
|
||||
It's super important that you really look at all your options and consider your use case before making a decision.
|
||||
:::
|
||||
|
||||
## Option 1: Wireless over WiFi 2.4 GHz
|
||||
### Wireless Capable ESPs:
|
||||
|
||||
* Seeed Studio XIAO Sense
|
||||
* ESP32-CAM
|
||||
* FREENOVE ESP32-S3-WROOM CAM Board
|
||||
|
||||
This offers a good starting point as the ESP32 CAM boards are cheaper than wired capable trackers.
|
||||
However, they can be a bit more temperamental and if you are using a wired headset, they don't really make sense.
|
||||
|
||||
**Pros:**
|
||||
- Not as experimental
|
||||
- Less cables (power only)
|
||||
- No issues with USB hubs
|
||||
|
||||
**Cons:**
|
||||
- Requires two external antennas for optimal streaming quality
|
||||
- Requires WiFi 2.4 GHz router or access point in reasonable proximity
|
||||
- High risk of radio interference with FBT and other WiFi 2.4 GHz devices
|
||||
- ESP32-CAM uses more power and heats up due to radio power needs
|
||||
|
||||
## Option 2: Wired over USB Serial (in beta)
|
||||
## Option 1: Wired over USB Serial
|
||||
### Wired Capable ESPs:
|
||||
* Seeed Studio XIAO Sense
|
||||
* FREENOVE ESP32-S3-WROOM CAM Board
|
||||
@ -55,10 +34,33 @@ This is our latest setup recommended for users with wired headsets such as the V
|
||||
**Pros:**
|
||||
- Much better performance and higher framerate up to 70 FPS with lower latency
|
||||
- No conflicts with advanced FBT setups such as Vive or Tundra Trackers
|
||||
- Can be wireless or wired
|
||||
- Less soldering required
|
||||
- Can be wireless *or* wired
|
||||
- Less soldering required compared to ESP32-CAM boards
|
||||
|
||||
**Cons:**
|
||||
- Requires USB port i.e. on Valve Index and USB hub mounted on your headset
|
||||
- Can be slightly more costly
|
||||
- When in use with a Vive Facial Tracker, an MTT USB hub is required
|
||||
- When in use with a Vive Facial Tracker or other bandwidth sensitive components, a MTT USB hub is required
|
||||
- Requires beta app versions until the v2.0 app is released
|
||||
|
||||
## Option 2: Wireless over WiFi 2.4 GHz
|
||||
### Wireless Capable ESPs:
|
||||
|
||||
* Seeed Studio XIAO Sense
|
||||
* ESP32-CAM
|
||||
* FREENOVE ESP32-S3-WROOM CAM Board
|
||||
|
||||
This offers a good starting point as the ESP32-CAM boards are cheaper than wired capable trackers.
|
||||
However, they can be a bit more temperamental and if you are using a wired headset, they don't really make sense.
|
||||
|
||||
**Pros:**
|
||||
- Less cables (power only)
|
||||
- No issues with USB hubs
|
||||
- Easier to flash
|
||||
- Less power draw
|
||||
|
||||
**Cons:**
|
||||
- Requires two external antennas for optimal streaming quality
|
||||
- Requires WiFi 2.4 GHz router or access point in reasonable proximity
|
||||
- High risk of radio interference with FBT and other WiFi 2.4 GHz devices
|
||||
- Uses more power and heats up due to radio power needs
|
Loading…
Reference in New Issue
Block a user