Skip to content

Commit 78bc99b

Browse files
committed
add action to control the split function
1 parent c37f1c8 commit 78bc99b

4 files changed

Lines changed: 194 additions & 0 deletions

File tree

manifest.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,18 @@
211211
"PropertyInspectorPath": "pi/empty.html",
212212
"Controllers": ["Keypad"],
213213
"States": [{ "Title": "Stop CW" }]
214+
},
215+
{
216+
"Name": "Set Split VFO",
217+
"UUID": "com.thecodingflow.hamlibplugin.setsplitvfo",
218+
"Tooltip": "Enable or disable split operation and set the TX VFO",
219+
"Icon": "icons/radio_light",
220+
"DisableAutomaticStates": false,
221+
"VisibleInActionsList": true,
222+
"SupportedInMultiActions": true,
223+
"PropertyInspectorPath": "pi/setsplitvfo.html",
224+
"Controllers": ["Keypad"],
225+
"States": [{ "Title": "Split" }]
214226
}
215227
],
216228
"OS": [{ "Platform": "linux" }],

pi/setsplitvfo.html

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<script>
5+
let update = () => {};
6+
let vfoSetting = "";
7+
let splitSetting = "false";
8+
let txvfoSetting = "";
9+
10+
function connectOpenActionSocket(
11+
inPort,
12+
inPropertyInspectorUUID,
13+
inRegisterEvent,
14+
inInfo,
15+
inActionInfo,
16+
) {
17+
const websocket = new WebSocket("ws://localhost:" + inPort);
18+
inActionInfo = JSON.parse(inActionInfo);
19+
websocket.onopen = () => {
20+
websocket.send(
21+
JSON.stringify({
22+
event: inRegisterEvent,
23+
uuid: inPropertyInspectorUUID,
24+
}),
25+
);
26+
};
27+
28+
vfoSetting = inActionInfo.payload.settings.vfo ?? "";
29+
splitSetting = inActionInfo.payload.settings.split ?? "false";
30+
txvfoSetting = inActionInfo.payload.settings.txvfo ?? "";
31+
32+
websocket.onmessage = (event) => {
33+
const data = JSON.parse(event.data);
34+
if (data.event == "didReceiveSettings") {
35+
vfoSetting = data.payload.settings.vfo ?? "";
36+
splitSetting = data.payload.settings.split ?? "false";
37+
txvfoSetting = data.payload.settings.txvfo ?? "";
38+
}
39+
if (data.event == "sendToPropertyInspector") {
40+
// TODO: receive available vfos from the plugin
41+
}
42+
};
43+
44+
const vfoElement = document.getElementById("vfo");
45+
vfoElement.value = inActionInfo.payload.settings.vfo ?? "";
46+
47+
const splitElement = document.getElementById("split");
48+
splitElement.checked =
49+
inActionInfo.payload.settings.split === "true";
50+
51+
const txvfoElement = document.getElementById("txvfo");
52+
txvfoElement.value = inActionInfo.payload.settings.txvfo ?? "";
53+
54+
update = () => {
55+
websocket.send(
56+
JSON.stringify({
57+
event: "setSettings",
58+
context: inActionInfo.context,
59+
payload: {
60+
vfo: vfoElement.value || "",
61+
split: splitElement.checked
62+
? "true"
63+
: "false",
64+
txvfo: txvfoElement.value || "",
65+
},
66+
}),
67+
);
68+
};
69+
}
70+
71+
const connectElgatoStreamDeckSocket = connectOpenActionSocket;
72+
</script>
73+
74+
<style>
75+
* {
76+
font-family: system-ui, sans-serif;
77+
font-size: 16px;
78+
color: oklch(92.2% 0 0);
79+
}
80+
body {
81+
margin: 16px;
82+
background-color: oklch(26.9% 0 0);
83+
}
84+
label {
85+
margin-right: 4px;
86+
}
87+
input {
88+
margin: 4px;
89+
padding: 4px;
90+
background-color: oklch(37.1% 0 0);
91+
border: 1px solid oklch(43.9% 0 0);
92+
border-radius: 8px;
93+
}
94+
input[type="checkbox"] {
95+
width: 18px;
96+
height: 18px;
97+
vertical-align: middle;
98+
}
99+
</style>
100+
</head>
101+
102+
<body>
103+
<div>
104+
<label for="vfo">VFO:</label>
105+
<!-- should be a combo box with all VFOs -->
106+
<input id="vfo" oninput="update()" type="text" />
107+
<br />
108+
<label for="split">Split:</label>
109+
<input id="split" onchange="update()" type="checkbox" />
110+
<br />
111+
<label for="txvfo">TX VFO:</label>
112+
<!-- should be a combo box with all VFOs -->
113+
<input id="txvfo" oninput="update()" type="text" />
114+
</div>
115+
</body>
116+
</html>

pkg/action/action.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type RigClient interface {
4949
SetXIT(hl.VFO, hl.Frequency) error
5050
GetPowerStatus() (hl.PowerStatus, error)
5151
SetPowerStatus(hl.PowerStatus) error
52+
SetSplitVFO(hl.VFO, bool, hl.VFO) error
5253
SetAntenna(hl.VFO, int, int) error
5354
SendMorse(string) error
5455
StopMorse() error

pkg/action/vfo.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ package action
22

33
import (
44
"log"
5+
"strconv"
56

67
sdk "github.com/SkYNewZ/streamdeck-sdk"
78
"github.com/ftl/hl-go"
89
)
910

1011
const (
1112
SelectVFOUUID = "com.thecodingflow.hamlibplugin.selectvfo"
13+
SetSplitVFOUUID = "com.thecodingflow.hamlibplugin.setsplitvfo"
1214
VFOOpUUID = "com.thecodingflow.hamlibplugin.vfoop"
1315
VFOOpEncoderUUID = "com.thecodingflow.hamlibplugin.vfoopencoder"
1416
)
1517

1618
func init() {
1719
Factories[SelectVFOUUID] = NewSelectVFO
20+
Factories[SetSplitVFOUUID] = NewSetSplitVFO
1821
Factories[VFOOpUUID] = NewVFOOp
1922
Factories[VFOOpEncoderUUID] = NewVFOOpEncoder
2023
}
@@ -200,3 +203,65 @@ func (a *VFOOpEncoder) DialDown(payload *sdk.ReceivedEventPayload) error {
200203
}
201204
return nil
202205
}
206+
207+
type SetSplitVFO struct {
208+
basicAction
209+
}
210+
211+
func NewSetSplitVFO(context string, client RigClient, deck Deck) Action {
212+
return &SetSplitVFO{
213+
basicAction: basicAction{
214+
context: context,
215+
client: client,
216+
deck: deck,
217+
},
218+
}
219+
}
220+
221+
func (a *SetSplitVFO) parseSettings(settings map[string]any) (hl.VFO, bool, hl.VFO) {
222+
vfo, ok := settings["vfo"].(string)
223+
if !ok {
224+
vfo = ""
225+
}
226+
splitString, ok := settings["split"].(string)
227+
if !ok {
228+
splitString = "false"
229+
}
230+
split, err := strconv.ParseBool(splitString)
231+
if err != nil {
232+
split = false
233+
}
234+
txVFO, ok := settings["txvfo"].(string)
235+
if !ok {
236+
txVFO = ""
237+
}
238+
return hl.VFO(vfo), split, hl.VFO(txVFO)
239+
}
240+
241+
func (a *SetSplitVFO) DidReceiveSettings(payload *sdk.ReceivedEventPayload) error {
242+
a.UpdateVisual(payload)
243+
return nil
244+
}
245+
246+
func (a *SetSplitVFO) UpdateVisual(payload *sdk.ReceivedEventPayload) error {
247+
_, split, _ := a.parseSettings(payload.Settings)
248+
title := "Split Off"
249+
if split {
250+
title = "Split On"
251+
}
252+
a.deck.SetTitle(a.context, title, sdk.HardwareAndSoftware)
253+
return nil
254+
}
255+
256+
func (a *SetSplitVFO) KeyDown(payload *sdk.ReceivedEventPayload) error {
257+
vfo, split, txVFO := a.parseSettings(payload.Settings)
258+
if vfo == "" || txVFO == "" {
259+
return nil
260+
}
261+
262+
err := a.client.SetSplitVFO(vfo, split, txVFO)
263+
if err != nil {
264+
log.Printf("[ERROR] set split vfo: %v", err)
265+
}
266+
return nil
267+
}

0 commit comments

Comments
 (0)