node-red-contrib-huawei-solar
Version:
Node-RED nodes for reading data from Huawei SmartLogger 3000 and SUN2000 inverters via Modbus TCP
220 lines (189 loc) • 11.3 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('sun2000', {
category: 'input',
color: '#ffcc66',
defaults: {
name: { value: "" },
host: { value: "", required: true, validate: RED.validators.regex(/^[a-zA-Z0-9.-]+$/) },
port: { value: 502, required: true, validate: RED.validators.number() },
inverterAddress: { value: 12, required: true, validate: RED.validators.number() },
useCustomName: { value: false },
deviceName: { value: "" },
dataDevice: { value: false },
dataPower: { value: true },
dataVoltages: { value: false },
dataCurrents: { value: false },
dataStrings: { value: false },
dataStatus: { value: false },
dataAlarms: { value: false },
alwaysIncludeAlarmTexts: { value: false },
namingConvention: { value: "descriptive", required: true },
timeout: { value: 5000, validate: RED.validators.number() },
retries: { value: 3, validate: RED.validators.number() },
continueOnFail: { value: false },
splitOutputs: { value: false },
outputs: { value: 1 }
},
inputs: 1,
outputs: 1,
icon: "icons/sun2000.svg",
label: function() {
return this.name || ("SUN2000-" + (this.inverterAddress || "12"));
},
oneditprepare: function() {
// Initialize outputs field
$("#node-input-outputs").val(this.outputs || 1);
// Handle split outputs toggle
$("#node-input-splitOutputs").change(function() {
$("#node-input-outputs").val($(this).is(':checked') ? 2 : 1);
});
// Set up custom name toggle
$("#node-input-useCustomName").change(function() {
if ($(this).is(':checked')) {
$(".form-row-custom-name").show();
} else {
$(".form-row-custom-name").hide();
}
});
// Trigger initial changes
$("#node-input-useCustomName").trigger('change');
$("#node-input-splitOutputs").trigger('change');
},
oneditsave: function() {
// Update outputs based on splitOutputs checkbox
$("#node-input-outputs").val($("#node-input-splitOutputs").is(':checked') ? 2 : 1);
}
});
</script>
<script type="text/html" data-template-name="sun2000">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-host"><i class="fa fa-server"></i> Host</label>
<input type="text" id="node-input-host" placeholder="SmartLogger IP address">
</div>
<div class="form-row">
<label for="node-input-port"><i class="fa fa-plug"></i> Port</label>
<input type="number" id="node-input-port" placeholder="502" min="1" max="65535">
</div>
<div class="form-row">
<label for="node-input-inverterAddress"><i class="fa fa-hashtag"></i> Inverter Address</label>
<input type="number" id="node-input-inverterAddress" placeholder="12" min="1" max="247">
<div class="form-tips">Modbus unit ID of the specific inverter to read</div>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-useCustomName" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-useCustomName" style="width: auto; margin-left: 5px;">Use Custom Name</label>
</div>
<div class="form-row form-row-custom-name" style="display:none; margin-left: 20px;">
<label for="node-input-deviceName"><i class="fa fa-edit"></i> Device Name</label>
<input type="text" id="node-input-deviceName" placeholder="East Roof Array">
</div>
<div class="form-row">
<label><i class="fa fa-list"></i> Data Categories</label>
<div style="margin-left: 20px;">
<input type="checkbox" id="node-input-dataDevice" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataDevice" style="width: auto; margin-left: 5px; margin-right: 20px;">Device Information</label>
<input type="checkbox" id="node-input-dataPower" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataPower" style="width: auto; margin-left: 5px; margin-right: 20px;">Power & Energy</label><br style="margin-bottom: 5px;">
<input type="checkbox" id="node-input-dataVoltages" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataVoltages" style="width: auto; margin-left: 5px; margin-right: 20px;">Grid Voltages</label>
<input type="checkbox" id="node-input-dataCurrents" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataCurrents" style="width: auto; margin-left: 5px; margin-right: 20px;">Grid Currents</label><br style="margin-bottom: 5px;">
<input type="checkbox" id="node-input-dataStrings" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataStrings" style="width: auto; margin-left: 5px; margin-right: 20px;">PV String Data</label>
<input type="checkbox" id="node-input-dataStatus" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataStatus" style="width: auto; margin-left: 5px; margin-right: 20px;">Status & Temperature</label><br style="margin-bottom: 5px;">
<input type="checkbox" id="node-input-dataAlarms" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dataAlarms" style="width: auto; margin-left: 5px;">Alarms & Faults</label>
</div>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-alwaysIncludeAlarmTexts" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-alwaysIncludeAlarmTexts" style="width: 70%;"> Always Include Alarm Texts</label>
<div class="form-tips">Include alarmTexts field in output even when empty</div>
</div>
<div class="form-row">
<label for="node-input-namingConvention"><i class="fa fa-font"></i> Field Naming</label>
<select id="node-input-namingConvention" style="width:70%;">
<option value="descriptive">Descriptive (activePower, phaseAVoltage)</option>
<option value="iec61850">IEC 61850 (P, Ua)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-timeout"><i class="fa fa-clock-o"></i> Timeout (ms)</label>
<input type="number" id="node-input-timeout" placeholder="5000" min="1000">
</div>
<div class="form-row">
<label for="node-input-retries"><i class="fa fa-refresh"></i> Retries</label>
<input type="number" id="node-input-retries" placeholder="3" min="0">
</div>
<div class="form-row">
<input type="checkbox" id="node-input-continueOnFail" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-continueOnFail" style="width: 70%;"> Continue on fail</label>
<div class="form-tips">Send error information as output instead of raising an error</div>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-splitOutputs" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-splitOutputs" style="width: 70%;"> Split telemetry and status outputs</label>
<div class="form-tips">Send telemetry data to output 1 and status data to output 2</div>
</div>
<input type="hidden" id="node-input-outputs"/>
</script>
<script type="text/html" data-help-name="sun2000">
<p>Reads detailed data from a single Huawei SUN2000 inverter via Modbus TCP through a SmartLogger gateway.</p>
<h3>Configuration</h3>
<p><strong>Connection:</strong> Configure the SmartLogger IP address, port (typically 502), and the specific inverter address to read.</p>
<p><strong>Inverter Address:</strong> The Modbus unit ID of the inverter (typically 12, 13, 14, 15, etc.).</p>
<p><strong>Data Categories:</strong> Select which types of data to read using checkboxes:</p>
<ul>
<li><strong>Device Information:</strong> Model, serial number, firmware version, specifications</li>
<li><strong>Power & Energy:</strong> Real-time power, daily/total energy, efficiency</li>
<li><strong>Grid Voltages:</strong> Line and phase voltages (UAB, UBC, UCA, Ua, Ub, Uc)</li>
<li><strong>Grid Currents:</strong> Phase currents and frequency</li>
<li><strong>PV String Data:</strong> Individual string voltages, currents, and power</li>
<li><strong>Status & Temperature:</strong> Device status, temperatures, insulation resistance</li>
<li><strong>Alarms & Faults:</strong> Comprehensive alarm decoding with readable messages</li>
</ul>
<p><strong>Field Naming:</strong> Choose between descriptive names (activePower) or IEC 61850 standard (P).</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>msg <span class="property-type">object</span></dt>
<dd>Any input message triggers data reading. The payload is ignored.</dd>
</dl>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>payload <span class="property-type">object</span></dt>
<dd>
<p>Inverter data with nested structure:</p>
<ul>
<li><code>ts</code> - Timestamp</li>
<li><code>unitId</code>, <code>deviceName</code> - Device identification</li>
<li><code>telemetry</code> - Power, voltage, current, and energy data</li>
<li><code>status</code> - Device status, temperatures, alarms</li>
</ul>
<p>If reading fails, an error message is sent instead.</p>
</dd>
</dl>
<h3>Usage</h3>
<p><strong>One node per inverter:</strong> Deploy separate SUN2000 nodes for each inverter you want to monitor.</p>
<p><strong>Modular design:</strong> Each node handles one inverter, making it easy to scale and manage.</p>
<p><strong>Flexible data:</strong> Choose exactly which data categories you need for each inverter.</p>
</script>
<style>
.form-row-manual, .form-row-discovery {
margin-left: 20px;
border-left: 3px solid #ddd;
padding-left: 10px;
}
.form-row-custom-names {
margin-left: 40px;
border-left: 2px solid #ccc;
padding-left: 10px;
}
.mapping-row {
margin-bottom: 5px;
}
</style>