diff --git a/.changeset/lemon-items-trade.md b/.changeset/lemon-items-trade.md new file mode 100644 index 00000000..4de03adb --- /dev/null +++ b/.changeset/lemon-items-trade.md @@ -0,0 +1,6 @@ +--- +"@ecoflow-api/rest-client": minor +"@ecoflow-api/schemas": minor +--- + +add Delta3 Pro support diff --git a/packages/rest-client/README.md b/packages/rest-client/README.md index 541a9c36..bc983989 100644 --- a/packages/rest-client/README.md +++ b/packages/rest-client/README.md @@ -32,6 +32,7 @@ At the moment the following devices are supported with specific instances: - Glacier - Smart Home Panel - Delta Pro +- Delta Pro 3 More devices to come. @@ -654,4 +655,4 @@ Use of the software is at your own risk and discretion, and I assume no liability for any potential damages or issues that may arise from using the software. It is important to be aware that using this open-source software comes -without direct support or guarantees from the company Ecoflow. \ No newline at end of file +without direct support or guarantees from the company Ecoflow. diff --git a/packages/rest-client/src/__fixtures__/deltaPro3Properties.ts b/packages/rest-client/src/__fixtures__/deltaPro3Properties.ts new file mode 100644 index 00000000..8c5ce83d --- /dev/null +++ b/packages/rest-client/src/__fixtures__/deltaPro3Properties.ts @@ -0,0 +1,118 @@ +export const deltaPro3Properties = { + code: "0" as const, + message: "Success" as const, + data: { + errcode: 0, + devSleepState: 1, + devStandbyTime: 1, + dcStandbyTime: 1, + bleStandbyTime: 1, + acStandbyTime: 1, + cmsMinDsgSoc: 0, + cmsChgDsgState: 1, + cmsBmsRunState: 1, + cmsBattSoc: 1.7, + cmsMaxChgSoc: 1, + cmsChgRemTime: 1, + cmsOilSelfStart: 0, + cmsOilOffSoc: 10, + cmsDsgRemTime: 10, + cmsOilOnSoc: 1, + bmsChgRemTime: 1, + bmsDesignCap: 10, + bmsMaxCellTemp: 10, + bmsBattSoc: 1.7, + bmsChgDsgState: 1, + bmsMinCellTemp: 10, + bmsDsgRemTime: 10, + powInSumW: 1.7, + powOutSumW: 1.7, + powGetAcHvOut: 1.7, + powGetAc: 1.7, + powGetTypec1: 1.7, + powGetTypec2: 1.7, + powGet12v: 1.7, + powGet24v: 1.7, + powGetAcLvOut: 1.7, + powGet5p8: 1.7, + powGetQcusb1: 1.7, + powGetQcusb2: 1.7, + powGet4p81: 1.7, + powGet4p82: 1.7, + powGetAcLvTt30Out: 1.7, + powGetPvH: 1.7, + powGetAcIn: 1.7, + powGetPvL: 1.7, + plugInInfoAcInChgHalPowMax: 1, + plugInInfoPvHChargerFlag: 0, + plugInInfo4p82InFlag: 1, + plugInInfoPvLChgAmpMax: 10, + plugInInfoAcInFeq: 50, + plugInInfoPvLType: 3, + plugInInfo5p8RunState: 1, + plugInInfo4p82RunState: 1, + plugInInfo4p81ChargerFlag: 0, + plugInInfo5p8ChgHalPowMax: 10, + plugInInfoPvHChgAmpMax: 10, + plugInInfo5p8DsgPowMax: 10, + plugInInfoAcInChgPowMax: 10, + plugInInfoPvHType: 3, + plugInInfo5p8ChargerFlag: 1, + plugInInfoAcInFlag: 0, + plugInInfo4p81DsgChgType: 3, + plugInInfoAcChargerFlag: 0, + plugInInfoPvHFlag: 0, + plugInInfo4p81Sn: "123456789", + plugInInfo4p82DsgChgType: 3, + plugInInfoPvHDcAmpMax: 10, + plugInInfo4p81InFlag: 1, + plugInInfo4p82ChargerFlag: 0, + plugInInfoPvLChgVolMax: 10, + plugInInfoPvLDcAmpMax: 10, + plugInInfo5p8Flag: 0, + plugInInfoAcOutDsgPowMax: 10, + plugInInfo5p8Sn: "123456789", + plugInInfoPvLChargerFlag: 0, + plugInInfo4p82Sn: "123456789", + plugInInfo5p8ChgPowMax: 10, + plugInInfoPvLFlag: 0, + plugInInfo4p81RunState: 10, + plugInInfoPvHChgVolMax: 10, + plugInInfo5p8DsgChg: 10, + flowInfoPvL: 2, + flowInfoPvH: 2, + flowInfoTypec1: 0, + flowInfoTypec2: 0, + flowInfoAcLvOut: 0, + flowInfo4p82Out: 0, + flowInfoAcIn: 2, + flowInfoAcHvOut: 2, + flowInfo12v: 2, + flowInfo24v: 2, + flowInfo4p81In: 2, + flowInfoQcusb1: 2, + flowInfoQcusb2: 2, + flowInfo4p82In: 2, + flowInfo5p8In: 2, + flowInfo4p81Out: 2, + flowInfo5p8Out: 2, + acEnergySavingOpen: 0, + multiBpChgDsgMode: 1, + fastChargeSwitch: 0, + lcdLight: 20, + energyBackupEn: 0, + acOutFreq: 10, + xboostEn: 1, + llcHvLvFlag: 10, + llcGFCIFlag: 0, + acLvAlwaysOn: 1, + screenOffTime: 10, + energyBackupStartSoc: 20, + acHvAlwaysOn: 0, + acAlwaysOnMiniSoc: 10, + enBeep: 0, + generatorPvHybridModeOpen: 0, + generatorCareModeOpen: 0, + generatorPvHybridModeSocMax: 10, + }, +}; diff --git a/packages/rest-client/src/__test__/shared.test.ts b/packages/rest-client/src/__test__/shared.test.ts index 8c504093..c4f86d84 100644 --- a/packages/rest-client/src/__test__/shared.test.ts +++ b/packages/rest-client/src/__test__/shared.test.ts @@ -15,6 +15,8 @@ import { SmartHomePanel } from "../lib/devices/SmartHomePanel"; import { shpProperties } from "../__fixtures__/shpProperties"; import { DeltaPro } from "../lib/devices/DeltaPro"; import { deltaProProperties } from "../__fixtures__/deltaProProperties"; +import { DeltaPro3 } from "../lib/devices/DeltaPro3"; +import { deltaPro3Properties } from "../__fixtures__/deltaPro3Properties"; type DeviceTestData = [ // device name @@ -80,6 +82,14 @@ const devices: DeviceTestData = [ "Invalid serial number for Delta Pro device.", "bmsMaster.soc", ], + [ + "Delta Pro 3", + DeltaPro3, + "MR51*****", + deltaPro3Properties, + "Invalid serial number for Delta Pro 3 device.", + "cmsMinDsgSoc", + ], ]; describe.each(devices)( diff --git a/packages/rest-client/src/lib/devices/DeltaPro3.test.ts b/packages/rest-client/src/lib/devices/DeltaPro3.test.ts new file mode 100644 index 00000000..946ead8a --- /dev/null +++ b/packages/rest-client/src/lib/devices/DeltaPro3.test.ts @@ -0,0 +1,235 @@ +import { beforeEach, describe, expect, it, jest } from "@jest/globals"; +import { RestClient, RestClientOptions } from "../RestClient"; +import { DeltaPro3 } from "./DeltaPro3"; + +describe("Delta Pro 3", () => { + let device: DeltaPro3; + let restClient: RestClient; + const validSn = "MR51*****"; + const defaultSetCommandParams = { + sn: validSn, + cmdFunc: 254, + dest: 2, + dirDest: 1, + needAck: true, + dirSrc: 1, + cmdId: 17, + }; + + beforeEach(() => { + const restClientOptions: RestClientOptions = { + host: "https://api-a.ecoflow.com", + accessKey: "fake_access", + secretKey: "fake_secret", + }; + + restClient = new RestClient(restClientOptions); + device = new DeltaPro3(restClient, validSn); + restClient.setCommandPlain = jest.fn(); + }); + + it.each([ + [ + false, + { + ...defaultSetCommandParams, + params: { + cfgBeepEn: false, + }, + }, + ], + [ + true, + { + ...defaultSetCommandParams, + params: { + cfgBeepEn: true, + }, + }, + ], + ])( + "sends the expected payload to enable and disable beep switch", + async (enabled, expectedPayload) => { + await device.enableBeep(enabled); + + expect(restClient.setCommandPlain).toBeCalledWith(expectedPayload); + }, + ); + + describe.each([ + ["setAcTimeout" as const, "cfgAcStandbyTime", [0, 2, 20], [-1, 1.1, "a"]], + ["setDcTimeout" as const, "cfgDcStandbyTime", [0, 2, 20], [-1, 1.1, "a"]], + [ + "setScreenTimeout" as const, + "cfgScreenOffTime", + [0, 2, 20], + [-1, 1.1, "a"], + ], + [ + "setDeviceTimeout" as const, + "cfgDevStandbyTime", + [0, 2, 20], + [-1, 1.1, "a"], + ], + ["setScreenBrightness" as const, "cfgLcdLight", [0, 2, 20], [-1, 1.1, "a"]], + [ + "enableHighVoltageAcOutput" as const, + "cfgHvAcOutOpen", + [true, false], + [-1, 0, "a"], + ], + [ + "enableLowVoltageAcOutput" as const, + "cfgLvAcOutOpen", + [true, false], + [-1, 0, "a"], + ], + [ + "setAcFrequency" as const, + "cfgAcOutFreq", + [50, 60], + [-1, 0, 90, 1.1, "a"], + ], + [ + "enable12VOut" as const, + "cfgDc12vOutOpen", + [true, false], + [-1, 0, 90, 1.1, "a"], + ], + [ + "enableXboost" as const, + "cfgXboostEn", + [true, false], + [-1, 0, 90, 1.1, "a"], + ], + ["shutdown" as const, "cfgPowerOff", [true], []], + ["setChargeLimit" as const, "cfgMaxChgSoc", [0, 1, 100], [-1, 300]], + ["setDischargeLimit" as const, "cfgMinDsgSoc", [0, 1, 100], [-1, 300]], + [ + "setLowVoltageMaxInput" as const, + "cfgPlugInInfoPvLDcAmpMax", + [0, 1, 2], + ["a-string"], + ], + [ + "setHighVoltageMaxInput" as const, + "cfgPlugInInfoPvHDcAmpMax", + [0, 1, 2], + ["a-string"], + ], + [ + "setMaxAcChargingPower" as const, + "cfgPlugInInfoAcInChgPowMax", + [0, 1, 2], + ["a-string"], + ], + [ + "setMaxChargingPowerIOPort" as const, + "cfgPlugInInfo5p8ChgPowMax", + [0, 1, 2], + ["a-string"], + ], + [ + "enableSmartGeneratorAutoStart" as const, + "cfgCmsOilSelfStart", + [true, false], + ["a-string", 1], + ], + [ + "setSmartGeneratorAutoStartSOC" as const, + "cfgCmsOilOnSoc", + [0, 1, 50, 100], + ["a-string", -1, 101], + ], + [ + "setSmartGeneratorAutoOffSOC" as const, + "cfgCmsOilOffSoc", + [0, 1, 50, 100], + ["a-string", -1, 101], + ], + [ + "enableGFCI" as const, + "cfgLlcGFCIFlag", + [true, false], + ["a-string", 1, 2], + ], + [ + "setBluetoothTimeout" as const, + "cfgBleStandbyTime", + [1, 2, 200, 10000], + ["a-string", -1, 10001], + ], + [ + "enableAcEnergySavingMode" as const, + "cfgAcEnergySavingOpen", + [true, false], + ["a-string", -1, 10001], + ], + [ + "setBatteryChargingDischargingOrder" as const, + "cfgMultiBpChgDsgMode", + [0, 1, 2], + ["a-string", -1, 10001], + ], + ])("%s", (fn, expectedParam, validValues, inValidValues) => { + it("sends expected payload", async () => { + await Promise.all( + validValues.map(async (val, index) => { + // @ts-expect-error + await device[fn](val); + expect(restClient.setCommandPlain).toHaveBeenNthCalledWith(++index, { + ...defaultSetCommandParams, + params: { + [expectedParam]: val, + }, + }); + }), + ); + }); + + it("error is thrown for invalid values", async () => { + await Promise.all( + inValidValues.map(async (val) => { + // @ts-expect-error + await expect(device[fn](val)).rejects.toThrowError(); + }), + ); + }); + }); + + describe("setBackupReserveLevel", () => { + it("sends expected payload", async () => { + await device.setBackupReserveLevel(10, true); + expect(restClient.setCommandPlain).toHaveBeenNthCalledWith(1, { + ...defaultSetCommandParams, + params: { + cfgEnergyBackup: { + energyBackupStartSoc: 10, + energyBackupEn: true, + }, + }, + }); + + await device.setBackupReserveLevel(10, false); + expect(restClient.setCommandPlain).toHaveBeenNthCalledWith(2, { + ...defaultSetCommandParams, + params: { + cfgEnergyBackup: { + energyBackupStartSoc: 10, + energyBackupEn: false, + }, + }, + }); + }); + + it("error is thrown for invalid values", async () => { + await expect( + device.setBackupReserveLevel(-1, false), + ).rejects.toThrowError(); + + await expect( + device.setBackupReserveLevel(101, true), + ).rejects.toThrowError(); + }); + }); +}); diff --git a/packages/rest-client/src/lib/devices/DeltaPro3.ts b/packages/rest-client/src/lib/devices/DeltaPro3.ts new file mode 100644 index 00000000..e611b42a --- /dev/null +++ b/packages/rest-client/src/lib/devices/DeltaPro3.ts @@ -0,0 +1,533 @@ +import { + DeltaPro3AcEnergySavingModeCommand, + deltaPro3AcEnergySavingModeCommandSchema, + DeltaPro3AcOutFreqCommand, + deltaPro3AcOutFreqCommandSchema, + DeltaPro3AcTimeoutCommand, + deltaPro3AcTimeoutCommandSchema, + DeltaPro3BatterChargingOrderCommand, + deltaPro3BatterChargingOrderCommandSchema, + DeltaPro3BeepEnCommand, + deltaPro3BeepEnCommandSchema, + DeltaPro3BleStandbyTimeCommand, + deltaPro3BleStandbyTimeCommandSchema, + DeltaPro3CmsOilOffSocCommand, + deltaPro3CmsOilOffSocCommandSchema, + DeltaPro3CmsOilOnSocCommand, + deltaPro3CmsOilOnSocCommandSchema, + DeltaPro3CmsOilSelfStartCommand, + deltaPro3CmsOilSelfStartCommandSchema, + DeltaPro3Dc12vOutOpenCommand, + deltaPro3Dc12vOutOpenCommandSchema, + DeltaPro3DcTimeoutCommand, + deltaPro3DcTimeoutCommandSchema, + DeltaPro3DeviceTimeoutCommand, + deltaPro3DeviceTimeoutCommandSchema, + DeltaPro3EnergyBackupCommand, + deltaPro3EnergyBackupCommandSchema, + DeltaPro3HvAcOutOpenCommand, + deltaPro3HvAcOutOpenCommandSchema, + DeltaPro3LlcGFCIFlagCommand, + deltaPro3LlcGFCIFlagCommandSchema, + DeltaPro3LvAcOutOpenCommand, + deltaPro3LvAcOutOpenCommandSchema, + DeltaPro3MaxChargingPowIOCommand, + deltaPro3MaxChargingPowIOCommandSchema, + DeltaPro3MaxChgSocCommand, + deltaPro3MaxChgSocCommandSchema, + DeltaPro3MinDsgSocCommand, + deltaPro3MinDsgSocCommandSchema, + DeltaPro3PlugInInfoPvHDcAmpMaxCommand, + deltaPro3PlugInInfoPvHDcAmpMaxCommandSchema, + DeltaPro3PlugInInfoPvLDcAmpMaxCommand, + deltaPro3PlugInInfoPvLDcAmpMaxCommandSchema, + DeltaPro3PowerOffCommand, + deltaPro3PowerOffCommandSchema, + DeltaPro3QuotaAll, + deltaPro3QuotaAllSchema, + DeltaPro3ScreenBrightnessCommand, + deltaPro3ScreenBrightnessCommandSchema, + DeltaPro3ScreenTimeoutCommand, + deltaPro3ScreenTimeoutCommandSchema, + DeltaPro3SerialNumber, + DeltaPro3SetMaxAcChargingPowCommand, + deltaPro3SetMaxAcChargingPowCommandSchema, + DeltaPro3XboostEnCommand, + deltaPro3XboostEnCommandSchema, + isDeltaPro3SerialNumber, +} from "@ecoflow-api/schemas"; +import { Device } from "./Device"; +import { RestClient } from "../RestClient"; + +export class DeltaPro3 extends Device< + DeltaPro3SerialNumber, + DeltaPro3QuotaAll +> { + constructor(restClient: RestClient, sn: DeltaPro3SerialNumber) { + super(restClient, sn); + + if (!isDeltaPro3SerialNumber(sn)) { + throw new Error("Invalid serial number for Delta Pro 3 device."); + } + } + + #payloadDefaults(params: T) { + const defaults = { + sn: this.sn, + cmdFunc: 254, + dest: 2, + dirDest: 1, + needAck: true, + dirSrc: 1, + cmdId: 17, + } as const; + + return { + ...defaults, + params: { + ...params, + }, + }; + } + + protected parseProperties(data: any) { + return deltaPro3QuotaAllSchema.parse(data); + } + + /** + * Sets the beeper switch + * + * @example + * ```typescript + * await device.enableBeep(false); + * await device.enableBeep(true); + * ``` + * + * @param enabled + */ + async enableBeep(enabled: boolean) { + const payload: DeltaPro3BeepEnCommand = this.#payloadDefaults({ + cfgBeepEn: enabled, + }); + + return this.sendCommand(payload, deltaPro3BeepEnCommandSchema); + } + + /** + * Sets AC timeout + * + * @example + * ```typescript + * await device.setAcTimeout(120); + * ``` + * + * @param minutes + */ + async setAcTimeout(minutes: number) { + const payload: DeltaPro3AcTimeoutCommand = this.#payloadDefaults({ + cfgAcStandbyTime: minutes, + }); + + return this.sendCommand(payload, deltaPro3AcTimeoutCommandSchema); + } + + /** + * Sets DC timeout + * + * @example + * ```typescript + * await device.setDcTimeout(120); + * ``` + * + * @param minutes + */ + async setDcTimeout(minutes: number) { + const payload: DeltaPro3DcTimeoutCommand = this.#payloadDefaults({ + cfgDcStandbyTime: minutes, + }); + return this.sendCommand(payload, deltaPro3DcTimeoutCommandSchema); + } + + /** + * Sets the screen timeout (s). + * + * @example + * ```typescript + * await device.setScreenTimeout(30); + * ``` + * + * @param seconds + */ + async setScreenTimeout(seconds: number) { + const payload: DeltaPro3ScreenTimeoutCommand = this.#payloadDefaults({ + cfgScreenOffTime: seconds, + }); + + return this.sendCommand(payload, deltaPro3ScreenTimeoutCommandSchema); + } + + /** + * Sets the device timeout (min). + * + * @example + * ```typescript + * await device.setDeviceTimeout(30); + * ``` + * + * @param minutes + */ + async setDeviceTimeout(minutes: number) { + const payload: DeltaPro3DeviceTimeoutCommand = this.#payloadDefaults({ + cfgDevStandbyTime: minutes, + }); + + return this.sendCommand(payload, deltaPro3DeviceTimeoutCommandSchema); + } + + /** + * Sets screen brightness + * + * @example + * ```typescript + * await device.setScreenBrightness(30); + * ``` + * + * @param brightness + */ + async setScreenBrightness(brightness: number) { + const payload: DeltaPro3ScreenBrightnessCommand = this.#payloadDefaults({ + cfgLcdLight: brightness, + }); + + return this.sendCommand(payload, deltaPro3ScreenBrightnessCommandSchema); + } + + /** + * High-voltage AC output switch. + * + * @example + * ```typescript + * await device.enableHighVoltageAcOutput(true); + * ``` + * + * @param enabled + */ + async enableHighVoltageAcOutput(enabled: boolean) { + const payload: DeltaPro3HvAcOutOpenCommand = this.#payloadDefaults({ + cfgHvAcOutOpen: enabled, + }); + + return this.sendCommand(payload, deltaPro3HvAcOutOpenCommandSchema); + } + + /** + * Low-voltage AC output switch + * + * @example + * ```typescript + * await device.enableLowVoltageAcOutput(true); + * ``` + * + * @param enabled + */ + async enableLowVoltageAcOutput(enabled: boolean) { + const payload: DeltaPro3LvAcOutOpenCommand = this.#payloadDefaults({ + cfgLvAcOutOpen: enabled, + }); + + return this.sendCommand(payload, deltaPro3LvAcOutOpenCommandSchema); + } + + /** + * Sets the AC output frequency (50Hz/60Hz). + * + * @example + * ```typescript + * await device.setAcFrequency(50); + * ``` + * + * @param freq - 50 or 60 Hz + */ + async setAcFrequency(freq: 50 | 60) { + const payload: DeltaPro3AcOutFreqCommand = this.#payloadDefaults({ + cfgAcOutFreq: freq, + }); + + return this.sendCommand(payload, deltaPro3AcOutFreqCommandSchema); + } + + /** + * 12V output switch. + * + * @example + * ```typescript + * await device.enable12VOut(true); + * ``` + * + * @param enabled + */ + async enable12VOut(enabled: boolean) { + const payload: DeltaPro3Dc12vOutOpenCommand = this.#payloadDefaults({ + cfgDc12vOutOpen: enabled, + }); + + return this.sendCommand(payload, deltaPro3Dc12vOutOpenCommandSchema); + } + + /** + * X-Boost switch. + * + * @example + * ```typescript + * await device.enableXboost(true); + * ``` + * + * @param enabled + */ + async enableXboost(enabled: boolean) { + const payload: DeltaPro3XboostEnCommand = this.#payloadDefaults({ + cfgXboostEn: enabled, + }); + + return this.sendCommand(payload, deltaPro3XboostEnCommandSchema); + } + + /** + * Shuts down the device. + * + * @example + * ```typescript + * await device.shutdown(); + * ``` + */ + async shutdown() { + const payload: DeltaPro3PowerOffCommand = this.#payloadDefaults({ + cfgPowerOff: true, + }); + return this.sendCommand(payload, deltaPro3PowerOffCommandSchema); + } + + /** + * Sets the charge limit. + * + * @example + * ```typescript + * await device.setChargeLimit(70); + * ``` + */ + async setChargeLimit(limit: number) { + const payload: DeltaPro3MaxChgSocCommand = this.#payloadDefaults({ + cfgMaxChgSoc: limit, + }); + return this.sendCommand(payload, deltaPro3MaxChgSocCommandSchema); + } + + /** + * Sets the discharge limit. + * + * @example + * ```typescript + * await device.setDischargeLimit(70); + * ``` + */ + async setDischargeLimit(limit: number) { + const payload: DeltaPro3MinDsgSocCommand = this.#payloadDefaults({ + cfgMinDsgSoc: limit, + }); + return this.sendCommand(payload, deltaPro3MinDsgSocCommandSchema); + } + + /** + * Sets the backup reserve level. + * + * @example + * ```typescript + * await device.setBackupReserveLevel(70,true); + * ``` + */ + async setBackupReserveLevel(start: number, enabled: boolean) { + const payload: DeltaPro3EnergyBackupCommand = this.#payloadDefaults({ + cfgEnergyBackup: { + energyBackupStartSoc: start, + energyBackupEn: enabled, + }, + }); + return this.sendCommand(payload, deltaPro3EnergyBackupCommandSchema); + } + + /** + * Sets the maximum input current of the low-voltage PV port. + * + * @example + * ```typescript + * await device.setLowVoltageMaxInput(7); + * ``` + */ + async setLowVoltageMaxInput(input: number) { + const payload: DeltaPro3PlugInInfoPvLDcAmpMaxCommand = + this.#payloadDefaults({ + cfgPlugInInfoPvLDcAmpMax: input, + }); + return this.sendCommand( + payload, + deltaPro3PlugInInfoPvLDcAmpMaxCommandSchema, + ); + } + + /** + * Sets the maximum input current of the high-voltage PV port. + * + * @example + * ```typescript + * await device.setHighVoltageMaxInput(12); + * ``` + */ + async setHighVoltageMaxInput(input: number) { + const payload: DeltaPro3PlugInInfoPvHDcAmpMaxCommand = + this.#payloadDefaults({ + cfgPlugInInfoPvHDcAmpMax: input, + }); + return this.sendCommand( + payload, + deltaPro3PlugInInfoPvHDcAmpMaxCommandSchema, + ); + } + + /** + * Sets the maximum AC charging power. + * + * @example + * ```typescript + * await device.setMaxAcChargingPower(3000); + * ``` + */ + async setMaxAcChargingPower(input: number) { + const payload: DeltaPro3SetMaxAcChargingPowCommand = this.#payloadDefaults({ + cfgPlugInInfoAcInChgPowMax: input, + }); + return this.sendCommand(payload, deltaPro3SetMaxAcChargingPowCommandSchema); + } + + /** + * Maximum charging power of the Power In/Out port. + * + * @example + * ```typescript + * await device.setMaxChargingPowerIOPort(1800); + * ``` + */ + async setMaxChargingPowerIOPort(input: number) { + const payload: DeltaPro3MaxChargingPowIOCommand = this.#payloadDefaults({ + cfgPlugInInfo5p8ChgPowMax: input, + }); + return this.sendCommand(payload, deltaPro3MaxChargingPowIOCommandSchema); + } + + /** + * Smart Generator auto start/stop switch. + * + * @example + * ```typescript + * await device.enableSmartGeneratorAutoStart(true); + * ``` + */ + async enableSmartGeneratorAutoStart(input: boolean) { + const payload: DeltaPro3CmsOilSelfStartCommand = this.#payloadDefaults({ + cfgCmsOilSelfStart: input, + }); + return this.sendCommand(payload, deltaPro3CmsOilSelfStartCommandSchema); + } + + /** + * Sets the SOC that automatically starts the Smart Generator. + * + * @example + * ```typescript + * await device.setSmartGeneratorAutoStartSOC(30); + * ``` + */ + async setSmartGeneratorAutoStartSOC(input: number) { + const payload: DeltaPro3CmsOilOnSocCommand = this.#payloadDefaults({ + cfgCmsOilOnSoc: input, + }); + return this.sendCommand(payload, deltaPro3CmsOilOnSocCommandSchema); + } + + /** + * Sets the SOC that automatically stops the Smart Generator. + * + * @example + * ```typescript + * await device.setSmartGeneratorAutoOffSOC(30); + * ``` + */ + async setSmartGeneratorAutoOffSOC(input: number) { + const payload: DeltaPro3CmsOilOffSocCommand = this.#payloadDefaults({ + cfgCmsOilOffSoc: input, + }); + return this.sendCommand(payload, deltaPro3CmsOilOffSocCommandSchema); + } + + /** + * GFCI switch. + * + * @example + * ```typescript + * await device.enableGFCI(true); + * ``` + */ + async enableGFCI(input: boolean) { + const payload: DeltaPro3LlcGFCIFlagCommand = this.#payloadDefaults({ + cfgLlcGFCIFlag: input, + }); + return this.sendCommand(payload, deltaPro3LlcGFCIFlagCommandSchema); + } + + /** + * Sets Bluetooth timeout. + * + * @example + * ```typescript + * await device.setBluetoothTimeout(200); + * ``` + */ + async setBluetoothTimeout(input: number) { + const payload: DeltaPro3BleStandbyTimeCommand = this.#payloadDefaults({ + cfgBleStandbyTime: input, + }); + return this.sendCommand(payload, deltaPro3BleStandbyTimeCommandSchema); + } + + /** + * AC energy-saving mode switch. + * + * @example + * ```typescript + * await device.enableAcEnergySavingMode(true); + * ``` + */ + async enableAcEnergySavingMode(input: boolean) { + const payload: DeltaPro3AcEnergySavingModeCommand = this.#payloadDefaults({ + cfgAcEnergySavingOpen: input, + }); + return this.sendCommand(payload, deltaPro3AcEnergySavingModeCommandSchema); + } + + /** + * Battery charging/discharging order. + * 0: default + * 1: The device will automatically decide the charge and discharge order based on each battery's voltage. + * 2: The main battery is prioritized during charging, and extra batteries are prioritized during discharging. + * + * @example + * ```typescript + * await device.setBatteryChargingDischargingOrder(1); + * ``` + */ + async setBatteryChargingDischargingOrder(input: number) { + const payload: DeltaPro3BatterChargingOrderCommand = this.#payloadDefaults({ + cfgMultiBpChgDsgMode: input, + }); + return this.sendCommand(payload, deltaPro3BatterChargingOrderCommandSchema); + } +} diff --git a/packages/rest-client/src/lib/devices/DeviceFactory.test.ts b/packages/rest-client/src/lib/devices/DeviceFactory.test.ts index 36cc0f58..35d12081 100644 --- a/packages/rest-client/src/lib/devices/DeviceFactory.test.ts +++ b/packages/rest-client/src/lib/devices/DeviceFactory.test.ts @@ -8,6 +8,7 @@ import { Delta2 } from "./Delta2"; import { Glacier } from "./Glacier"; import { SmartHomePanel } from "./SmartHomePanel"; import { DeltaPro } from "./DeltaPro"; +import { DeltaPro3 } from "./DeltaPro3"; describe("deviceFactory", () => { let restClient: RestClient; @@ -20,50 +21,57 @@ describe("deviceFactory", () => { }); }); - it("returns a SmartPlug instance when the serial number is for a SmartPlug", () => { + it("returns a SmartPlug instance", () => { const device = deviceFactory("HW52*****", restClient); expect(device).toBeInstanceOf(SmartPlug); expect(device.sn).toBe("HW52*****"); }); - it("returns a UnknownDevice instance when the serial number can not be mapped to a device", () => { + it("returns a UnknownDevice instance", () => { const device = deviceFactory("fake_sn", restClient); expect(device).toBeInstanceOf(UnknownDevice); expect(device.sn).toBe("fake_sn"); }); - it("returns a PowerStream instance when the serial number is for a PowerStream", () => { + it("returns a PowerStream instance", () => { const sn = "HW51*****"; const device = deviceFactory(sn, restClient); expect(device).toBeInstanceOf(PowerStream); expect(device.sn).toBe(sn); }); - it("returns a Delta 2 instance when the serial number is for a Delta 2", () => { + it("returns a Delta 2 instance", () => { const sn = "R331*****"; const device = deviceFactory(sn, restClient); expect(device).toBeInstanceOf(Delta2); expect(device.sn).toBe(sn); }); - it("returns a Glacier instance when the serial number is for a Glacier", () => { + it("returns a Glacier instance", () => { const sn = "BX11*****"; const device = deviceFactory(sn, restClient); expect(device).toBeInstanceOf(Glacier); expect(device.sn).toBe(sn); }); - it("returns a SHP instance when the serial number is for a SHP", () => { + it("returns a SHP instance", () => { const sn = "SP10*****"; const device = deviceFactory(sn, restClient); expect(device).toBeInstanceOf(SmartHomePanel); expect(device.sn).toBe(sn); }); - it("returns a Delta Pro instance when the serial number is for a DP", () => { + it("returns a Delta Pro instance", () => { const sn = "DCABZ*****"; const device = deviceFactory(sn, restClient); expect(device).toBeInstanceOf(DeltaPro); expect(device.sn).toBe(sn); }); + + it("returns a Delta Pro 3 instance", () => { + const sn = "MR51*****"; + const device = deviceFactory(sn, restClient); + expect(device).toBeInstanceOf(DeltaPro3); + expect(device.sn).toBe(sn); + }); }); diff --git a/packages/rest-client/src/lib/devices/DeviceFactory.ts b/packages/rest-client/src/lib/devices/DeviceFactory.ts index 6294fb78..7ac1c8e1 100644 --- a/packages/rest-client/src/lib/devices/DeviceFactory.ts +++ b/packages/rest-client/src/lib/devices/DeviceFactory.ts @@ -1,8 +1,9 @@ import { Delta2SerialNumber, - DeltaProSerialNumber, + DeltaPro3SerialNumber, GlacierSerialNumber, isDelta2SerialNumber, + isDeltaPro3SerialNumber, isDeltaProSerialNumber, isGlacierSerialNumber, isPowerStreamSerialNumber, @@ -20,6 +21,7 @@ import { Delta2 } from "./Delta2"; import { Glacier } from "./Glacier"; import { SmartHomePanel } from "./SmartHomePanel"; import { DeltaPro } from "./DeltaPro"; +import { DeltaPro3 } from "./DeltaPro3"; // prettier-ignore export type DeviceFactoryReturnType = @@ -28,7 +30,7 @@ export type DeviceFactoryReturnType = T extends Delta2SerialNumber ? Delta2 : T extends GlacierSerialNumber ? Glacier : T extends SmartHomePanelSerialNumber ? SmartHomePanel : - T extends DeltaProSerialNumber ? DeltaPro : + T extends DeltaPro3SerialNumber ? DeltaPro3 : UnknownDevice; /** @@ -64,5 +66,9 @@ export function deviceFactory>( return new DeltaPro(restClient, sn) as R; } + if (isDeltaPro3SerialNumber(sn)) { + return new DeltaPro3(restClient, sn) as R; + } + return new UnknownDevice(restClient, sn) as R; } diff --git a/packages/schemas/src/deltaPro3/getProperties.ts b/packages/schemas/src/deltaPro3/getProperties.ts new file mode 100644 index 00000000..c87faf3a --- /dev/null +++ b/packages/schemas/src/deltaPro3/getProperties.ts @@ -0,0 +1,283 @@ +import { z } from "zod"; +import { integer, zeroOrOne, zeroOrOneOrTwo } from "../shared"; + +export const deltaPro3QuotaAllSchema = z + .object({ + // int - Device error code + errcode: integer, + // int - Sleep status + devSleepState: integer, + // int - Device timeout (min). + // 0: the device will never sleep + devStandbyTime: integer, + // int - DC timeout (min). + // 0: DC output ports will never time out + dcStandbyTime: integer, + // int - Bluetooth timeout (h). + // 0: Bluetooth will never time out + bleStandbyTime: integer, + // int - AC timeout (min). + // 0: AC output ports will never time out. + acStandbyTime: integer, + // int - Discharge limit. + cmsMinDsgSoc: integer, + // int - Charging/Discharging status. + // 0: not charging or discharging, + // 1: discharging, + // 2: charging. + cmsChgDsgState: zeroOrOneOrTwo, + // int - On/Off status. 0: off, 1: on. + cmsBmsRunState: zeroOrOne, + // float - Overall SOC + cmsBattSoc: z.number().min(0).max(100), + // int - Charge limit + cmsMaxChgSoc: integer, + // int - Remaining charging time (min) + cmsChgRemTime: integer, + // bool - Smart Generator auto start/stop switch. + cmsOilSelfStart: zeroOrOne, + // int - SOC for automatically stopping the Smart Generator. + cmsOilOffSoc: integer, + // int - Remaining discharging time (min). + cmsDsgRemTime: integer, + // int - SOC for automatically stopping the Smart Generator. + cmsOilOnSoc: integer, + // int - Remaining charging time of the main battery (min). + bmsChgRemTime: integer, + // int - Battery capacity (mAh). + bmsDesignCap: integer, + // int - Temperature of the main battery (°C). + bmsMaxCellTemp: integer, + // float - SOC of the main battery. + bmsBattSoc: z.number().min(0).max(100), + // int - Charging/Discharging status of the main battery. + // 0: not charging/discharging, + // 1: discharging, + // 2: charging. + bmsChgDsgState: zeroOrOneOrTwo, + // int - Minimum temperature of the main battery (°C). + bmsMinCellTemp: integer, + // int - Remaining discharging time (min). + bmsDsgRemTime: integer, + // float - Total input power (W). + powInSumW: z.number(), + // float - Total output power (W). + powOutSumW: z.number(), + // float - Real-time grid power (W). + powGetAcHvOut: z.number(), + // float - Real-time AC power (W). + powGetAc: z.number(), + // float - Real-time power of Type-C port 1 (W). + powGetTypec1: z.number(), + // float - Real-time power of Type-C port 2 (W). + powGetTypec2: z.number(), + // float - Real-time 12V power (W). + powGet12v: z.number(), + // float - Real-time 24V power (W). + powGet24v: z.number(), + // float - Real-time low-voltage AC output power (W). + powGetAcLvOut: z.number(), + // float - Real-time power of the Power In/Out port (W). + powGet5p8: z.number(), + // float - Real-time power of the USB 1 port (W). + powGetQcusb1: z.number(), + // float - Real-time power of the USB 2 port (W). + powGetQcusb2: z.number(), + // float - Real-time power of Extra Battery Port 1 (W). + powGet4p81: z.number(), + // float - Real-time power of Extra Battery Port 2 (W). + powGet4p82: z.number(), + // float - Real-time power of the low-voltage AC output port (W). + powGetAcLvTt30Out: z.number(), + // float - Real-time high-voltage PV power (W). + powGetPvH: z.number(), + // float - Real-time AC input power (W). + powGetAcIn: z.number(), + // float - Real-time low-voltage PV power (W). + powGetPvL: z.number(), + // int - Maximum AC charging power. + plugInInfoAcInChgHalPowMax: integer, + // bool - PV connection status. + // 0: disconnected, + // 1: connected. + plugInInfoPvHChargerFlag: zeroOrOne, + // int - Indicates whether the Extra Battery port is connected. + // 0: disconnected, + // 1: connected. + plugInInfo4p82InFlag: zeroOrOne, + // int - Maximum charging current of the PV port. + plugInInfoPvLChgAmpMax: integer, + // int - AC input frequency. + plugInInfoAcInFeq: integer, + // int - PV port charging mode. + // 1: car charging, + // 2: solar charging, + // 3: DC charging. + plugInInfoPvLType: z.literal(1).or(z.literal(2)).or(z.literal(3)), + // int - Operating status of the device connected to the Power In/Out port. + plugInInfo5p8RunState: integer, + // int - Operating status of the device connected to Extra Battery Port 2. + plugInInfo4p82RunState: integer, + // bool - Identifier of charger connection to Extra Battery Port 1. 0: disconnected, 1: connected. + plugInInfo4p81ChargerFlag: zeroOrOne, + // int - Operating status of the device connected to the Power In/Out port. + plugInInfo5p8ChgHalPowMax: integer, + // int - Maximum charging current of the high-voltage PV port (A). + plugInInfoPvHChgAmpMax: integer, + // int - Maximum discharging power of the Power In/Out port. + plugInInfo5p8DsgPowMax: integer, + // int - Maximum AC charging power (W). + plugInInfoAcInChgPowMax: integer, + // int - High-voltage PV port charging mode. 1: car charging, 2: solar charging, 3: DC charging. + plugInInfoPvHType: z.literal(1).or(z.literal(2)).or(z.literal(3)), + // bool - Operating status of the device connected to the Power In/Out port. + plugInInfo5p8ChargerFlag: zeroOrOne, + // int - Indicates whether the AC charging port is connected. 0: disconnected, 1: connected. + plugInInfoAcInFlag: zeroOrOne, + // int - Charging/Discharging type of Extra Battery Port 1. + // 0: reserved, + // 1: charging/discharging, + // 2: charging only, + // 3: discharging only. + plugInInfo4p81DsgChgType: z + .literal(0) + .or(z.literal(1)) + .or(z.literal(2)) + .or(z.literal(3)), + // bool - Indicates whether the charger is connected to the AC port. + // 0: disconnected, + // 1: connected. + plugInInfoAcChargerFlag: zeroOrOne, + // int - Indicates whether the high-voltage PV port is connected. + // 0: disconnected, + // 1: connected. + plugInInfoPvHFlag: zeroOrOne, + // string - SN of the device connected to the Extra Battery port. + plugInInfo4p81Sn: z.string(), + // int - Charging/Discharging type of Extra Battery Port 2. + // 1: charging/discharging, + // 2: charging only, + // 3: discharging only. + plugInInfo4p82DsgChgType: z.literal(1).or(z.literal(2)).or(z.literal(3)), + // int - Maximum DC input current of the high-voltage PV port (A). + plugInInfoPvHDcAmpMax: integer, + // int - Indicates whether Extra Battery Port 1 is connected. + // 0: disconnected, + // 1: connected. + plugInInfo4p81InFlag: zeroOrOne, + // bool - Identifier of charger connection to Extra Battery Port 2. + // 0: disconnected, + // 1: connected. + plugInInfo4p82ChargerFlag: zeroOrOne, + // int - Maximum charging voltage of the low-voltage PV port (V). + plugInInfoPvLChgVolMax: integer, + // int - Maximum DC input current of the low-voltage PV port (A). + plugInInfoPvLDcAmpMax: integer, + // int - Indicates whether the Power In/Out port is connected. + // 0: disconnected, + // 1: connected. + plugInInfo5p8Flag: zeroOrOne, + // int - Maximum AC discharging power. + plugInInfoAcOutDsgPowMax: integer, + // string - SN of the device connected to the Power In/Out port. + plugInInfo5p8Sn: z.string(), + // bool - Identifier of charger connection to the low-voltage PV port. + // 0: disconnected, + // 1: connected. + plugInInfoPvLChargerFlag: zeroOrOne, + // string - SN of the ecosystem product connected to Extra Battery Port 2. + plugInInfo4p82Sn: z.string(), + // int - Maximum charging power of the Power In/Out port. + plugInInfo5p8ChgPowMax: integer, + // int - Indicates whether the low-voltage PV port is connected. + // 0: disconnected, + // 1: connected. + plugInInfoPvLFlag: zeroOrOne, + // int - Operating status of the device connected to Extra Battery Port 1. + plugInInfo4p81RunState: integer, + // int - Maximum charging voltage of the high-voltage PV port (V). + plugInInfoPvHChgVolMax: integer, + // int - Charging/Discharging type of the Power In/Out port. + plugInInfo5p8DsgChg: integer, + // int - Low-voltage PV switch status. (0: off, 2: on.) + flowInfoPvL: z.literal(0).or(z.literal(2)), + // int - High-voltage PV switch status. (0: off, 2: on.) + flowInfoPvH: z.literal(0).or(z.literal(2)), + // int - Type-C port 1 switch status. (0: off, 2: on.) + flowInfoTypec1: z.literal(0).or(z.literal(2)), + // int - Type-C port 2 switch status. (0: off, 2: on.) + flowInfoTypec2: z.literal(0).or(z.literal(2)), + // int - AC low-voltage output switch status. (0: off, 2: on.) + flowInfoAcLvOut: z.literal(0).or(z.literal(2)), + // int - Extra Battery port output switch status. (0: off, 2: on.) + flowInfo4p82Out: z.literal(0).or(z.literal(2)), + // int - AC input switch status. (0: off, 2: on.) + flowInfoAcIn: z.literal(0).or(z.literal(2)), + // int - High-voltage AC output switch status. (0: off, 2: on.) + flowInfoAcHvOut: z.literal(0).or(z.literal(2)), + // int - 12V output switch status. (0: off, 2: on.) + flowInfo12v: z.literal(0).or(z.literal(2)), + // int - 24V output switch status. (0: off, 2: on.) + flowInfo24v: z.literal(0).or(z.literal(2)), + // int - Extra Battery Port 1 input switch status. (0: off, 2: on.) + flowInfo4p81In: z.literal(0).or(z.literal(2)), + // int - USB output port 1 switch status. (0: off, 2: on.) + flowInfoQcusb1: z.literal(0).or(z.literal(2)), + // int - USB output port 2 switch status. (0: off, 2: on.) + flowInfoQcusb2: z.literal(0).or(z.literal(2)), + // int - Extra Battery Port 2 input switch status. (0: off, 2: on.) + flowInfo4p82In: z.literal(0).or(z.literal(2)), + // int - Power In/Out port switch status. (0: off, 2: on.) + flowInfo5p8In: z.literal(0).or(z.literal(2)), + // int - Extra Battery Port 1 switch status. (0: off, 2: on.) + flowInfo4p81Out: z.literal(0).or(z.literal(2)), + // int - Power In/Out port switch status. (0: off, 2: on.) + flowInfo5p8Out: z.literal(0).or(z.literal(2)), + // bool - AC energy-saving mode switch. 0: off, 1: on. + acEnergySavingOpen: zeroOrOne, + // int - Battery charging/discharging order. + // 0: default + // 1: The device will automatically decide the charge and discharge order based on each battery's voltage. + // 2: The main battery is prioritized during charging, and extra batteries are prioritized during discharging. + multiBpChgDsgMode: zeroOrOneOrTwo, + // int - Fast charging slider switch. + // 0: fast charging; + // 1: custom charging power. + fastChargeSwitch: zeroOrOne, + // int - Screen brightness. + lcdLight: integer, + // bool - Backup reserve function switch. + // 0: off, + // 1: on. + energyBackupEn: zeroOrOne, + // int - AC output frequency. + acOutFreq: integer, + // bool - X-Boost switch. 0: off, 1: on. + xboostEn: zeroOrOne, + // int - High-voltage/Low-voltage AC identifier. + llcHvLvFlag: integer, + // bool - GFCI switch. + llcGFCIFlag: zeroOrOne, + // bool - AC Always-on. + acLvAlwaysOn: zeroOrOne, + // int - Screen timeout (s). + // 0: The screen will never time out. Other values: using the value you set (unit: s). + screenOffTime: integer, + // int - Backup reserve level. + energyBackupStartSoc: integer, + // bool - Sets the High-voltage AC Always-on function. 0: off. 1: on. + acHvAlwaysOn: zeroOrOne, + // int - Sets the minimum SOC to enable the AC Always-on function. + acAlwaysOnMiniSoc: integer, + // bool - Indicates whether the beeper is turned on. 0: off, 1: on. + enBeep: zeroOrOne, + // bool - Generator and solar energy hybrid mode. 0: off, 1: on. + generatorPvHybridModeOpen: zeroOrOne, + // bool - Night care mode switch. 0: off, 1: on. + generatorCareModeOpen: zeroOrOne, + // int - Maximum SOC in the generator and solar energy hybrid mode + generatorPvHybridModeSocMax: integer, + }) + .passthrough(); + +export type DeltaPro3QuotaAll = z.infer; diff --git a/packages/schemas/src/deltaPro3/index.ts b/packages/schemas/src/deltaPro3/index.ts new file mode 100644 index 00000000..8e0c823a --- /dev/null +++ b/packages/schemas/src/deltaPro3/index.ts @@ -0,0 +1,3 @@ +export * from "./setCommands"; +export * from "./getProperties"; +export * from "./serialNumber"; diff --git a/packages/schemas/src/deltaPro3/serialNumber.ts b/packages/schemas/src/deltaPro3/serialNumber.ts new file mode 100644 index 00000000..94359eb0 --- /dev/null +++ b/packages/schemas/src/deltaPro3/serialNumber.ts @@ -0,0 +1,18 @@ +import { z } from "zod"; + +/********************************************* + * Serial number + * Delta Pro 3 serial number to start with "MR51" + *********************************************/ + +export const deltaPro3SerialNumberSchema = z.custom<`MR51${string}`>((val) => { + return typeof val === "string" ? val.startsWith("MR51") : false; +}); + +export type DeltaPro3SerialNumber = z.infer; + +export const isDeltaPro3SerialNumber = ( + x: unknown, +): x is DeltaPro3SerialNumber => { + return deltaPro3SerialNumberSchema.safeParse(x).success; +}; diff --git a/packages/schemas/src/deltaPro3/setCommands.ts b/packages/schemas/src/deltaPro3/setCommands.ts new file mode 100644 index 00000000..99b05b57 --- /dev/null +++ b/packages/schemas/src/deltaPro3/setCommands.ts @@ -0,0 +1,684 @@ +import { z } from "zod"; +import { deltaPro3SerialNumberSchema } from "./serialNumber"; +import { integer } from "../shared"; + +export const deltaPro3BaseSchema = z.object({ + sn: deltaPro3SerialNumberSchema, + cmdId: z.literal(17), + dirDest: z.literal(1), + dirSrc: z.literal(1), + cmdFunc: z.literal(254), + dest: z.literal(2), + needAck: z.literal(true), +}); + +export type DeltaPro3BaseCommand = z.infer; + +/** + * Sets the beeper switch. (true: on, false: off.) + * { + * sn: "MR51ZAS2PG330026", + * cmdId: 17, + * dirDest: 1, + * dirSrc: 1, + * cmdFunc: 254, + * dest: 2, + * needAck: true, + * params: { + * cfgBeepEn: true, + * }, + * } + */ +export const deltaPro3BeepEnCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgBeepEn: z.boolean(), + }), +}); + +export type DeltaPro3BeepEnCommand = z.infer< + typeof deltaPro3BeepEnCommandSchema +>; + +/** + * Sets AC timeout (min). + * + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgAcStandbyTime": 120 + * } + * } + */ +export const deltaPro3AcTimeoutCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgAcStandbyTime: integer.min(0), + }), +}); + +export type DeltaPro3AcTimeoutCommand = z.infer< + typeof deltaPro3AcTimeoutCommandSchema +>; + +/** + * Sets DC timeout (min). + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgDcStandbyTime": 120 + * } + * } + */ +export const deltaPro3DcTimeoutCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgDcStandbyTime: integer.min(0), + }), +}); + +export type DeltaPro3DcTimeoutCommand = z.infer< + typeof deltaPro3DcTimeoutCommandSchema +>; + +/** + * Sets the screen timeout (s). + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgScreenOffTime": 30 + * } + * } + */ +export const deltaPro3ScreenTimeoutCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgScreenOffTime: integer.min(0), + }), +}); + +export type DeltaPro3ScreenTimeoutCommand = z.infer< + typeof deltaPro3ScreenTimeoutCommandSchema +>; + +/** + * Sets the device timeout (min). + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgDevStandbyTime": 30 + * } + * } + */ +export const deltaPro3DeviceTimeoutCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgDevStandbyTime: integer.min(0), + }), +}); + +export type DeltaPro3DeviceTimeoutCommand = z.infer< + typeof deltaPro3DeviceTimeoutCommandSchema +>; + +/** + * Sets screen brightness. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgLcdLight": 30 + * } + * } + */ +export const deltaPro3ScreenBrightnessCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgLcdLight: integer.min(0), + }), + }); + +export type DeltaPro3ScreenBrightnessCommand = z.infer< + typeof deltaPro3ScreenBrightnessCommandSchema +>; + +/** + * High-voltage AC output switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgHvAcOutOpen": true + * } + * } + */ +export const deltaPro3HvAcOutOpenCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgHvAcOutOpen: z.boolean(), + }), +}); + +export type DeltaPro3HvAcOutOpenCommand = z.infer< + typeof deltaPro3HvAcOutOpenCommandSchema +>; + +/** + * Low-voltage AC output switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgLvAcOutOpen": true + * } + * } + */ +export const deltaPro3LvAcOutOpenCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgLvAcOutOpen: z.boolean(), + }), +}); + +export type DeltaPro3LvAcOutOpenCommand = z.infer< + typeof deltaPro3LvAcOutOpenCommandSchema +>; + +/** + * Sets the AC output frequency (50Hz/60Hz). + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgAcOutFreq": 50 + * } + * } + */ +export const deltaPro3AcOutFreqCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgAcOutFreq: z.literal(50).or(z.literal(60)), + }), +}); + +export type DeltaPro3AcOutFreqCommand = z.infer< + typeof deltaPro3AcOutFreqCommandSchema +>; + +/** + * 12V output switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgDc12vOutOpen": true + * } + * } + */ +export const deltaPro3Dc12vOutOpenCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgDc12vOutOpen: z.boolean(), + }), +}); + +export type DeltaPro3Dc12vOutOpenCommand = z.infer< + typeof deltaPro3Dc12vOutOpenCommandSchema +>; + +/** + * X-Boost switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgXboostEn": true + * } + * } + */ +export const deltaPro3XboostEnCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgXboostEn: z.boolean(), + }), +}); + +export type DeltaPro3XboostEnCommand = z.infer< + typeof deltaPro3XboostEnCommandSchema +>; + +/** + * Shuts down the device. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgPowerOff": true + * } + * } + */ +export const deltaPro3PowerOffCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgPowerOff: z.boolean(), + }), +}); + +export type DeltaPro3PowerOffCommand = z.infer< + typeof deltaPro3PowerOffCommandSchema +>; + +/** + * Sets the charge limit. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgMaxChgSoc": 70 + * } + * } + */ +export const deltaPro3MaxChgSocCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgMaxChgSoc: z.number().int().min(0).max(100), + }), +}); + +export type DeltaPro3MaxChgSocCommand = z.infer< + typeof deltaPro3MaxChgSocCommandSchema +>; + +/** + * Sets the discharge limit. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgMinDsgSoc": 30 + * } + * } + */ +export const deltaPro3MinDsgSocCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgMinDsgSoc: z.number().int().min(0).max(100), + }), +}); + +export type DeltaPro3MinDsgSocCommand = z.infer< + typeof deltaPro3MinDsgSocCommandSchema +>; + +/** + * Sets the backup reserve level. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgEnergyBackup": { + * "energyBackupStartSoc": 40, + * "energyBackupEn": true + * } + * } + * } + */ +export const deltaPro3EnergyBackupCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgEnergyBackup: z.object({ + energyBackupStartSoc: z.number().int().min(0).max(100), + energyBackupEn: z.boolean(), + }), + }), +}); + +export type DeltaPro3EnergyBackupCommand = z.infer< + typeof deltaPro3EnergyBackupCommandSchema +>; + +/** + * Sets the maximum input current of the low-voltage PV port. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgPlugInInfoPvLDcAmpMax": 7 + * } + * } + */ +export const deltaPro3PlugInInfoPvLDcAmpMaxCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgPlugInInfoPvLDcAmpMax: z.number().int(), + }), + }); + +export type DeltaPro3PlugInInfoPvLDcAmpMaxCommand = z.infer< + typeof deltaPro3PlugInInfoPvLDcAmpMaxCommandSchema +>; + +/** + * Sets the maximum input current of the high-voltage PV port. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgPlugInInfoPvHDcAmpMax": 12 + * } + * } + */ +export const deltaPro3PlugInInfoPvHDcAmpMaxCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgPlugInInfoPvHDcAmpMax: z.number().int(), + }), + }); + +export type DeltaPro3PlugInInfoPvHDcAmpMaxCommand = z.infer< + typeof deltaPro3PlugInInfoPvHDcAmpMaxCommandSchema +>; + +/** + * Sets the maximum AC charging power. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgPlugInInfoAcInChgPowMax": 3000 + * } + * } + */ +export const deltaPro3SetMaxAcChargingPowCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgPlugInInfoAcInChgPowMax: z.number().int(), + }), + }); + +export type DeltaPro3SetMaxAcChargingPowCommand = z.infer< + typeof deltaPro3SetMaxAcChargingPowCommandSchema +>; + +/** + * Maximum charging power of the Power In/Out port. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgPlugInInfo5p8ChgPowMax": 1800 + * } + * } + */ +export const deltaPro3MaxChargingPowIOCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgPlugInInfo5p8ChgPowMax: z.number().int(), + }), + }); + +export type DeltaPro3MaxChargingPowIOCommand = z.infer< + typeof deltaPro3MaxChargingPowIOCommandSchema +>; + +/** + * Smart Generator auto start/stop switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgCmsOilSelfStart": true + * } + * } + */ +export const deltaPro3CmsOilSelfStartCommandSchema = deltaPro3BaseSchema.extend( + { + params: z.object({ + cfgCmsOilSelfStart: z.boolean(), + }), + }, +); + +export type DeltaPro3CmsOilSelfStartCommand = z.infer< + typeof deltaPro3CmsOilSelfStartCommandSchema +>; + +/** + * Sets the SOC that automatically starts the Smart Generator. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgCmsOilOnSoc": 36 + * } + * } + */ +export const deltaPro3CmsOilOnSocCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgCmsOilOnSoc: z.number().int().min(0).max(100), + }), +}); + +export type DeltaPro3CmsOilOnSocCommand = z.infer< + typeof deltaPro3CmsOilOnSocCommandSchema +>; + +/** + * Sets the SOC that automatically stops the Smart Generator. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgCmsOilOffSoc": 67 + * } + * } + */ +export const deltaPro3CmsOilOffSocCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgCmsOilOffSoc: z.number().int().min(0).max(100), + }), +}); + +export type DeltaPro3CmsOilOffSocCommand = z.infer< + typeof deltaPro3CmsOilOffSocCommandSchema +>; + +/** + * GFCI switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgLlcGFCIFlag": true + * } + * } + */ +export const deltaPro3LlcGFCIFlagCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgLlcGFCIFlag: z.boolean(), + }), +}); + +export type DeltaPro3LlcGFCIFlagCommand = z.infer< + typeof deltaPro3LlcGFCIFlagCommandSchema +>; + +/** + * Sets Bluetooth timeout. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgBleStandbyTime": 200 + * } + * } + */ +export const deltaPro3BleStandbyTimeCommandSchema = deltaPro3BaseSchema.extend({ + params: z.object({ + cfgBleStandbyTime: z.number().int().min(0).max(10000), + }), +}); + +export type DeltaPro3BleStandbyTimeCommand = z.infer< + typeof deltaPro3BleStandbyTimeCommandSchema +>; + +/** + * AC energy-saving mode switch. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgAcEnergySavingOpen": true + * } + * } + */ +export const deltaPro3AcEnergySavingModeCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgAcEnergySavingOpen: z.boolean(), + }), + }); + +export type DeltaPro3AcEnergySavingModeCommand = z.infer< + typeof deltaPro3AcEnergySavingModeCommandSchema +>; + +/** + * Battery charging/discharging order. + * 0: default + * 1: The device will automatically decide the charge and discharge order based on each battery's voltage. + * 2: The main battery is prioritized during charging, and extra batteries are prioritized during discharging. + * { + * "sn": "MR51ZAS2PG330026", + * "cmdId": 17, + * "dirDest": 1, + * "dirSrc": 1, + * "cmdFunc": 254, + * "dest": 2, + * "needAck": true, + * "params": { + * "cfgMultiBpChgDsgMode": 1 + * } + * } + */ +export const deltaPro3BatterChargingOrderCommandSchema = + deltaPro3BaseSchema.extend({ + params: z.object({ + cfgMultiBpChgDsgMode: z.number().int().min(0).max(2), + }), + }); + +export type DeltaPro3BatterChargingOrderCommand = z.infer< + typeof deltaPro3BatterChargingOrderCommandSchema +>; diff --git a/packages/schemas/src/index.ts b/packages/schemas/src/index.ts index c1da3dae..01f0bc30 100644 --- a/packages/schemas/src/index.ts +++ b/packages/schemas/src/index.ts @@ -6,3 +6,4 @@ export * from "./wave2"; export * from "./smartHomePanel"; export * from "./deltaPro"; export * from "./shared"; +export * from "./deltaPro3";