diff --git a/assets/js/components/Config/DeviceModal/Modbus.vue b/assets/js/components/Config/DeviceModal/Modbus.vue
index 1568972aa..acf3fb724 100644
--- a/assets/js/components/Config/DeviceModal/Modbus.vue
+++ b/assets/js/components/Config/DeviceModal/Modbus.vue
@@ -46,7 +46,7 @@
class="me-2"
required
:model-value="id || defaultId"
- @input="$emit('update:id', $event.target.value)"
+ @update:model-value="(v) => $emit('update:id', v)"
/>
@@ -62,7 +62,7 @@
class="me-2"
required
:model-value="host"
- @input="$emit('update:host', $event.target.value)"
+ @update:model-value="(v) => $emit('update:host', v)"
/>
@@ -73,7 +73,7 @@
class="me-2 w-50"
required
:model-value="port || defaultPort"
- @input="$emit('update:port', $event.target.value)"
+ @update:model-value="(v) => $emit('update:port', v)"
/>
$emit('update:baudrate', parseInt(v))"
/>
@@ -154,7 +154,7 @@
:choice="comsetOptions"
required
:model-value="comset || defaultComset"
- @input="$emit('update:comset', $event.target.value)"
+ @update:model-value="(v) => $emit('update:comset', v)"
/>
@@ -263,9 +263,9 @@ export default defineComponent({
this.setProtocolByCapabilities(newValue);
this.$emit("update:modbus", this.selectedModbus);
},
- modbus(newValue: MODBUS_TYPE) {
+ modbus(newValue: MODBUS_TYPE, oldValue: MODBUS_TYPE) {
if (newValue) {
- this.setConnectionAndProtocolByModbus(newValue);
+ this.setConnectionAndProtocolByModbus(newValue, oldValue);
}
},
connection(newValue: MODBUS_CONNECTION, oldValue: MODBUS_CONNECTION) {
@@ -298,8 +298,8 @@ export default defineComponent({
? MODBUS_PROTOCOL.TCP
: MODBUS_PROTOCOL.RTU;
},
- setConnectionAndProtocolByModbus(modbus?: MODBUS_TYPE) {
- switch (modbus) {
+ setConnectionAndProtocolByModbus(newModbus?: MODBUS_TYPE, oldModbus?: MODBUS_TYPE) {
+ switch (newModbus) {
case MODBUS_TYPE.RS485_SERIAL:
this.connection = MODBUS_CONNECTION.SERIAL;
this.protocol = MODBUS_PROTOCOL.RTU;
@@ -313,6 +313,11 @@ export default defineComponent({
this.protocol = MODBUS_PROTOCOL.TCP;
break;
}
+
+ // when switching from serial to TCP/IP, default protocol to Modbus-TCP (rtu=false)
+ if (oldModbus === MODBUS_TYPE.RS485_SERIAL && newModbus === MODBUS_TYPE.RS485_TCPIP) {
+ this.protocol = MODBUS_PROTOCOL.TCP;
+ }
},
formId(name: string): string {
return `${name}-${this.componentId}`;
diff --git a/assets/js/components/Config/ModbusProxyConnection.vue b/assets/js/components/Config/ModbusProxyConnection.vue
new file mode 100644
index 000000000..981aa6193
--- /dev/null
+++ b/assets/js/components/Config/ModbusProxyConnection.vue
@@ -0,0 +1,126 @@
+
+ updateHost(host)"
+ @update:port="(port) => updatePort(port)"
+ @update:modbus="(modbus) => updateModbus(modbus)"
+ />
+
+
+
diff --git a/assets/js/components/Config/ModbusProxyModal.vue b/assets/js/components/Config/ModbusProxyModal.vue
index d1a051c8a..e0f7eb1d2 100644
--- a/assets/js/components/Config/ModbusProxyModal.vue
+++ b/assets/js/components/Config/ModbusProxyModal.vue
@@ -85,19 +85,12 @@
- updateHost(host, c.settings)"
- @update:port="(port) => updatePort(port, c.settings)"
- @update:modbus="(modbus) => updateModbus(c.settings, modbus)"
+ (values[index] = connection)
+ "
/>
@@ -143,17 +136,13 @@ import "@h2d2/shopicons/es/regular/arrowdown";
import "@h2d2/shopicons/es/regular/plus";
import "@h2d2/shopicons/es/regular/trash";
import JsonModal from "./JsonModal.vue";
-import {
- MODBUS_COMSET,
- MODBUS_CONNECTION,
- MODBUS_PROTOCOL,
- MODBUS_PROXY_READONLY,
- MODBUS_TYPE,
- type ModbusProxy,
- type ModbusProxySettings,
-} from "@/types/evcc";
+import { MODBUS_PROXY_READONLY, type ModbusProxy } from "@/types/evcc";
import ASCII_DIAGRAM from "./modbus-diagram.txt?raw";
-import Modbus from "./DeviceModal/Modbus.vue";
+import ModbusProxyConnection, {
+ DEFAULT_BAUDRATE,
+ DEFAULT_COMSET,
+ DEFAULT_PORT,
+} from "./ModbusProxyConnection.vue";
import PropertyField from "./PropertyField.vue";
import FormRow from "./FormRow.vue";
import SponsorTokenRequired from "./DeviceModal/SponsorTokenRequired.vue";
@@ -162,7 +151,14 @@ import { defineComponent } from "vue";
export default defineComponent({
name: "ModbusProxyModal",
- components: { JsonModal, Modbus, FormRow, PropertyField, SponsorTokenRequired, SelectGroup },
+ components: {
+ JsonModal,
+ ModbusProxyConnection,
+ FormRow,
+ PropertyField,
+ SponsorTokenRequired,
+ SelectGroup,
+ },
props: {
isSponsor: Boolean,
},
@@ -170,10 +166,6 @@ export default defineComponent({
data() {
return {
ASCII_DIAGRAM,
- MODBUS_PROXY_READONLY,
- MODBUS_CONNECTION,
- MODBUS_PROTOCOL,
- MODBUS_TYPE,
};
},
computed: {
@@ -188,12 +180,6 @@ export default defineComponent({
formId(index: number, name: string) {
return `modbusproxy-connection-${index}-${name}`;
},
- getModbus(s: ModbusProxySettings) {
- if (s.device) {
- return MODBUS_TYPE.RS485_SERIAL;
- }
- return s.rtu ? MODBUS_TYPE.RS485_TCPIP : MODBUS_TYPE.TCPIP;
- },
getReadonlyHelp(readonly = MODBUS_PROXY_READONLY.FALSE): string {
return this.$t(`config.modbusproxy.readonly.help.${readonly}`);
},
@@ -203,41 +189,12 @@ export default defineComponent({
port: highestPort + 1,
readonly: MODBUS_PROXY_READONLY.FALSE,
settings: {
- uri: ":502",
- baudrate: 9600,
- comset: "8N1" as MODBUS_COMSET,
+ uri: `:${DEFAULT_PORT}`,
+ baudrate: DEFAULT_BAUDRATE,
+ comset: DEFAULT_COMSET,
},
});
},
- getHost(uri?: string) {
- return uri?.split(":")[0] || "";
- },
- getPort(uri?: string) {
- return uri?.split(":")[1] || "";
- },
- updateHost(newHost: string, settings: ModbusProxySettings) {
- const port = this.getPort(settings.uri);
- settings.uri = `${newHost}:${port}`;
- },
- updatePort(newPort: string | number, settings: ModbusProxySettings) {
- const host = this.getHost(settings.uri);
- settings.uri = `${host}:${newPort}`;
- },
- updateModbus(settings: ModbusProxySettings, modbus: MODBUS_TYPE) {
- switch (modbus) {
- case MODBUS_TYPE.RS485_SERIAL:
- settings.uri = undefined;
- settings.rtu = undefined;
- break;
- case MODBUS_TYPE.RS485_TCPIP:
- case MODBUS_TYPE.TCPIP:
- settings.device = undefined;
- settings.baudrate = undefined;
- settings.comset = undefined;
- settings.rtu = modbus === MODBUS_TYPE.RS485_TCPIP;
- break;
- }
- },
},
});
diff --git a/tests/config-modbusproxy.spec.ts b/tests/config-modbusproxy.spec.ts
index 2762fc764..383074d3d 100644
--- a/tests/config-modbusproxy.spec.ts
+++ b/tests/config-modbusproxy.spec.ts
@@ -87,6 +87,35 @@ test.describe("modbusproxy", async () => {
await expect(modal).not.toContainText("Connection #1");
});
+ test("modbusproxy serial defaults", async ({ page }) => {
+ await start();
+ await page.goto("/#/config");
+
+ const modbusproxyCard = page.getByTestId("modbusproxy");
+ await modbusproxyCard.getByRole("button", { name: "edit" }).click();
+ const modal = page.getByTestId("modbusproxy-modal");
+ await expectModalVisible(modal);
+
+ await modal.getByRole("button", { name: "Add proxy connection" }).click();
+ const deviceBox = modal.getByTestId("device-box");
+
+ await expect(deviceBox.getByLabel("Network")).toBeChecked();
+ await expect(deviceBox.getByLabel("Port")).toHaveValue("502");
+
+ // switch to RS485
+ await deviceBox.getByText("RS485", { exact: true }).click();
+ await expect(deviceBox.getByLabel("Baud rate")).toHaveValue("9600");
+ await expect(deviceBox.getByLabel("ComSet")).toHaveValue("8N1");
+
+ await deviceBox.getByLabel("Baud rate").selectOption("19200");
+
+ // switch to Network and back: defaults restored
+ await deviceBox.getByText("Network").click();
+ await deviceBox.getByText("RS485", { exact: true }).click();
+ await expect(deviceBox.getByLabel("Baud rate")).toHaveValue("9600");
+ await expect(deviceBox.getByLabel("ComSet")).toHaveValue("8N1");
+ });
+
test("modbusproxy via db (yaml to json migration)", async ({ page }) => {
await start(undefined, CONFIG_MODBUSPROXY_MIGRATE);
await page.goto("/#/config");