Skip to content

Commit 69c09b8

Browse files
feat: add limelight support
1 parent 434e784 commit 69c09b8

5 files changed

Lines changed: 92 additions & 12 deletions

File tree

src/App.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import xmlBuilder from "./lib/xmlBuilder.js";
55
import {createEmptyLynxModule, createEmptyMotorLynxModule, type LynxModule, type MotorLynxModule} from "./lib";
66
import MotorHub from "./lib/MotorHub.svelte";
7+
import ExpansionHub from "./lib/ExpansionHub.svelte";
78
89
let controlHub: MotorLynxModule = $state(createEmptyMotorLynxModule());
910
let expansionHub: MotorLynxModule = $state(createEmptyMotorLynxModule());
@@ -21,7 +22,7 @@
2122
class="lg:block bg-base-200 mb-16 lg:mb-0 lg:rounded-md lg:shadow-sm lg:border-2 lg:border-base-content/20 p-4 lg:p-6">
2223
<div class="tabs tabs-lift h-[calc(100%---spacing(10))]">
2324
<MotorHub name="Control Hub" bind:module={controlHub} checked={true}/>
24-
<MotorHub name="Expansion Hub" bind:module={expansionHub}/>
25+
<ExpansionHub name="Expansion Hub" bind:module={expansionHub}/>
2526
<Hub name="Servo Hub" bind:module={servoHub}/>
2627
</div>
2728
</div>

src/lib/ExpansionHub.svelte

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script lang="ts">
2+
import {type Device, DeviceTypes, type LynxModule, type ExpansionLynxModule} from "./index";
3+
import DeviceGroup from "./DeviceGroup.svelte";
4+
5+
interface Props {
6+
name: string;
7+
checked?: boolean;
8+
module: ExpansionLynxModule;
9+
}
10+
11+
let {name, checked = false, module = $bindable()}: Props = $props();
12+
</script>
13+
14+
<input type="radio" name="hub" class="tab" aria-label={name} {checked}/>
15+
<div class="tab-content bg-base-100 border-base-300 p-6">
16+
<DeviceGroup type="Motors" bind:devices={module.motors} deviceTypes={DeviceTypes.MOTORS}/>
17+
<DeviceGroup type="Servos" bind:devices={module.servos} deviceTypes={DeviceTypes.SERVOS}/>
18+
<DeviceGroup type="I<sup>2</sup>C Devices" bind:devices={module.i2c} deviceTypes={DeviceTypes.I2C}/>
19+
<DeviceGroup type="Digital Devices" bind:devices={module.digital} deviceTypes={DeviceTypes.DIGITAL}/>
20+
<DeviceGroup type="Analog Devices" bind:devices={module.analog} deviceTypes={DeviceTypes.ANALOG}/>
21+
<!-- Diffrence between ExpansionHub and MotorHub is that ExpansionHub doesn't have ethernet devices cause there are no useable usb ports -->
22+
<!-- This also means that I changed the thing in App.svelte to use the new ExpansionHub layout -->
23+
</div>

src/lib/MotorHub.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
<DeviceGroup type="I<sup>2</sup>C Devices" bind:devices={module.i2c} deviceTypes={DeviceTypes.I2C}/>
1919
<DeviceGroup type="Digital Devices" bind:devices={module.digital} deviceTypes={DeviceTypes.DIGITAL}/>
2020
<DeviceGroup type="Analog Devices" bind:devices={module.analog} deviceTypes={DeviceTypes.ANALOG}/>
21+
<DeviceGroup type="Ethernet Devices" bind:devices={module.ethernet} deviceTypes={DeviceTypes.ETHERNET}/>
2122
</div>

src/lib/index.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ export interface MotorLynxModule extends LynxModule {
1818
i2c: Device[];
1919
digital: Device[];
2020
analog: Device[];
21+
ethernet: Device[]
22+
}
23+
24+
export interface ExpansionLynxModule extends LynxModule {
25+
motors: Device[];
26+
i2c: Device[];
27+
digital: Device[];
28+
analog: Device[];
2129
}
2230

2331
export function createEmptyLynxModule(): LynxModule {
@@ -32,7 +40,18 @@ export function createEmptyMotorLynxModule(): MotorLynxModule {
3240
servos: [],
3341
i2c: [],
3442
digital: [],
35-
analog: []
43+
analog: [],
44+
ethernet:[],
45+
}
46+
}
47+
48+
export function createEmptyExpansionLynxModule(): ExpansionLynxModule {
49+
return {
50+
motors: [],
51+
servos: [],
52+
i2c: [],
53+
digital: [],
54+
analog: [],
3655
}
3756
}
3857

@@ -191,6 +210,12 @@ export const DeviceTypes = {
191210
type: 'AnalogDevice',
192211
displayName: 'Analog Device'
193212
}
213+
],
214+
ETHERNET: [
215+
{
216+
type: 'EthernetDevice',
217+
displayName: 'Limelight 3a'
218+
}
194219
]
195220
} as const;
196221

src/lib/xmlBuilder.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {LynxModule, MotorLynxModule} from "./index";
1+
import type {ExpansionLynxModule, LynxModule, MotorLynxModule} from "./index";
22
import {create} from "xmlbuilder2";
33
import type {XMLBuilder} from "xmlbuilder2/lib/interfaces";
44

@@ -8,16 +8,28 @@ export interface CodeBuilder {
88

99
class XmlBuilder implements CodeBuilder {
1010
build(controlHub: MotorLynxModule, expansionHub: MotorLynxModule, servoHub: LynxModule): string {
11-
const doc = create({version: '1.0', standalone: true, encoding: "UTF-8"})
12-
.ele("Robot", {type: "FirstInspires-FTC"})
13-
.ele("LynxUsbDevice", {name: "Control Hub Portal", serialNumber: "(embedded)", parentModuleAddress: 173})
14-
const controlHubBuilder = doc.ele("LynxModule", {name: "Control Hub", port: 173});
15-
XmlBuilder.buildMotorLynxModule(controlHubBuilder, controlHub);
16-
const expansionHubBuilder = doc.ele("LynxModule", {name: "Expansion Hub 0", port: 0});
17-
XmlBuilder.buildMotorLynxModule(expansionHubBuilder, expansionHub);
18-
const servoHubBuilder = doc.ele("LynxModule", {name: "Servo Hub 1", port: 1});
19-
XmlBuilder.buildLynxModule(servoHubBuilder, servoHub);
11+
const doc = create({version: '1.0', standalone: true, encoding: "UTF-8"});
2012

13+
const robotBlock = doc.ele("Robot", {type: "FirstInspires-FTC"});
14+
for(const ethernet of controlHub.ethernet) {
15+
robotBlock.ele("EthernetDevice", {name: ethernet.name, serialNumber: "EthernetOverUsb:eth0:172.29.0.28", port: "-1", ipAddress: "172.29.0.1"});
16+
}
17+
18+
const portalBlock = robotBlock.ele("LynxUsbDevice", {name: "Control Hub Portal", serialNumber: "(embedded)", parentModuleAddress: 173});
19+
20+
const controlHubBlock = portalBlock.ele("LynxModule", {name: "Control Hub", port: 173});
21+
XmlBuilder.buildMotorLynxModule(controlHubBlock, controlHub);
22+
23+
if(expansionHub.analog.length !== 0 || expansionHub.digital.length !== 0 || expansionHub.i2c.length !== 0 || expansionHub.motors.length !== 0 || expansionHub.servos.length !== 0) {
24+
const expansionHubBuilder = portalBlock.ele("LynxModule", {name: "Expansion Hub 0", port: 0});
25+
XmlBuilder.buildExpansionLynxModule(expansionHubBuilder, expansionHub);
26+
}
27+
28+
if(servoHub.servos.length !== 0) {
29+
const servoHubBuilder = portalBlock.ele("LynxModule", {name: "Servo Hub 1", port: 1});
30+
XmlBuilder.buildLynxModule(servoHubBuilder, servoHub);
31+
}
32+
2133
return doc.end({prettyPrint: true});
2234
}
2335

@@ -44,6 +56,24 @@ class XmlBuilder implements CodeBuilder {
4456
doc.ele(analog.type.type, {name: analog.name, port: analog.port});
4557
}
4658
}
59+
60+
private static buildExpansionLynxModule(doc: XMLBuilder, module: ExpansionLynxModule) {
61+
for (const motor of module.motors) {
62+
doc.ele(motor.type.type, {name: motor.name, port: motor.port});
63+
}
64+
for (const servo of module.servos) {
65+
doc.ele(servo.type.type, {name: servo.name, port: servo.port});
66+
}
67+
for (const i2c of module.i2c) {
68+
doc.ele(i2c.type.type, {name: i2c.name, port: 0, bus: i2c.port});
69+
}
70+
for (const digital of module.digital) {
71+
doc.ele(digital.type.type, {name: digital.name, port: digital.port});
72+
}
73+
for (const analog of module.analog) {
74+
doc.ele(analog.type.type, {name: analog.name, port: analog.port});
75+
}
76+
}
4777
}
4878

4979
export default new XmlBuilder();

0 commit comments

Comments
 (0)