Hallo allerseits,
mit folgendem Script lässt sich ein Energiemessgerät vom Typ Raritan BCM (Branch Circuit Monitor) in IP-Symcon einbinden. Die BCM ist zum Einbau in die Elektro-Verteilung vorgesehen und überwacht den Spannung, Frequenz, Strom, Wirk- und Scheinleistung und Energieverbrauch von bis zu 21 Verbrauchern. Jeweils drei Kanäle können auch zusammengefasst werden, um einen dreiphasig angeschlossenen Verbraucher zu überwachen.
Die Kommunikation zwischen IP-Symcon und BCM erfolgt über Modbus/TCP. Das Script legt alle benötigten Instanzen selbständig an, es muss nur in den ersten Zeilen die IP-Adresse und die Kanalkonfiguration angepasst werden. In der BCM muss der Modbus-Dienst unter Device Services/Network/Modbus eingeschaltet werden.
Achtung: Das Script legt je nach Konfiguration bis zu 160 neue Variablen an (21 Kanäle mit je 7 Sensoren). Bitte vorher prüfen, ob diese Anzahl von der gewählten IP-Symcon-Lizenz unterstützt wird. Notfalls können nicht benötigte Sensoren auskommentiert werden.
Die BCM ist ab sofort zu Preisen zwischen 700,- und 1600,- Euro je nach Ausführung erhältlich. Eine Bezugsquelle im deutschen Elektro-Großhandel ist die Schlegel-Gruppe. Für weitere Bezugsquellen oder Rückfragen benutzen sie bitte die folgende E-Mail-Adresse: sales.germany@raritan.com
Datenblatt: http://partners.raritan.eu/resources/BCM_deutsch_Mai2013.pdf
Schöne Grüße
Ingo
PS: Dies ist mein erstes Script für IP-Symcon, konstruktive Kritik ist willkommen.
<?
# IP-Symcon configuration script for Raritan BCM branch circuit monitor
# Communication is handled via Modbus/TCP.
# Attention: This script will create >100 new variables; please make sure
# this is supported by your IP-Symcon license!
# Root category name for all created sensor instances
$name = 'BCM-2400';
# Host name/IP address and port number. Please make sure to enable the
# Modbus/TCP service in Device Settings/Services/Modbus.
$host = 'my-bcm.raritan.com';
$port = 502;
# Branch circuit configuration
# BCM-2400 has 7*3 branch circuit meters. Each set of meters can be used
# to measure either one three-phase branch or three single-phase branches.
$circuits = array(
3, # Circuits 1, 2, 3: three-phase branch
3, # Circuits 4, 5, 6: three-phase branch
1, # Circuits 7, 8, 9: three single-phase branches
1, # Circuits 10, 11, 12: three single-phase branches
3, # Circuits 13, 14, 15: three-phase branch
1, # Circuits 16, 17, 18: three single-phase branches
1, # Circuits 19, 20, 21: three single-phase branches
);
# Module GUIDs
define('MODBUS_RTU_TCP', '{A5F663AB-C400-4FE5-B207-4D67CC030564}');
define('MODBUS_ADDRESS', '{CB197E50-273D-4535-8C91-BB35273E3CA5}');
define('ARCHIVE_CONTROL', '{43192F0B-135B-4CE7-A0A7-1475603F3060}');
# Create missing variable profiles
function createProfiles() {
$profiles = array(
'RaritanVoltage' => array('type' => 2, 'unit' => 'V', 'digits' => 0),
'RaritanCurrent' => array('type' => 2, 'unit' => 'A', 'digits' => 2),
'RaritanCurrentUnbalance' => array('type' => 2, 'unit' => '%', 'digits' => 0),
'RaritanActivePower' => array('type' => 2, 'unit' => 'W', 'digits' => 0),
'RaritanApparentPower' => array('type' => 2, 'unit' => 'VA', 'digits' => 0),
'RaritanPowerFactor' => array('type' => 2, 'unit' => '', 'digits' => 2),
'RaritanActiveEnergy' => array('type' => 1, 'unit' => 'Wh', 'digits' => 0),
'RaritanLineFrequency' => array('type' => 2, 'unit' => 'Hz', 'digits' => 1),
);
foreach ($profiles as $name => $settings) {
if (!IPS_VariableProfileExists($name)) {
if (!IPS_CreateVariableProfile($name, $settings['type']) ||
!IPS_SetVariableProfileText($name, '', ' ' . $settings['unit']) ||
!IPS_SetVariableProfileDigits($name, $settings['digits']))
{
trigger_error("Failed to create variable profile '$name'", E_USER_ERROR);
}
}
}
}
# Create a new category
# $name - Category name
# $parent - Optional: Logical parent
# $pos - Optional: Position in parent category
function createCategory($name, $parent = false, $pos = 0) {
$cat = IPS_CreateCategory();
IPS_SetName($cat, $name);
if ($parent != false)
IPS_SetParent($cat, $parent);
IPS_SetPosition($cat, $pos);
return $cat;
}
# Find the single instance of the Arcive Control module. This
# will raise an error in case fewer or more instances are found.
function getArchiveInstance() {
static $archive;
if (empty($archive)) {
$archives = IPS_GetInstanceListByModuleID(ARCHIVE_CONTROL);
if (count($archives) == 0)
trigger_error('No Archive Control instance found', E_USER_ERROR);
elseif (count($archives) > 1)
trigger_error('More than one Archive Control instance found', E_USER_ERROR);
$archive = $archives[0];
}
return $archive;
}
# Create Client Socket and ModBus RTU TCP instances
# $host - Host name or IP address
# $port - TCP port
# $name - Name for ModBus RTU TCP instance
function createModbus($host, $port, $name) {
$modbus = IPS_CreateInstance(MODBUS_RTU_TCP);
IPS_SetName($modbus, "Modbus/TCP @ $name");
IPS_SetProperty($modbus, 'SwapWords', 0);
IPS_ApplyChanges($modbus);
IPS_Sleep(500); # required for IP-Symcon 2.x where instances are connected asynchronously
$socket = IPS_GetInstanceParentID($modbus);
IPS_SetName($socket, "$host:$port");
IPS_SetProperty($socket, 'Host', $host);
IPS_SetProperty($socket, 'Port', $port);
IPS_SetProperty($socket, 'Open', 1);
IPS_ApplyChanges($socket);
return $modbus;
}
# Create a new sensor instance
# $category - Parent category
# $pos - Position in parent category
# $name - Name of new sensor instance
# $modbus - ModBus RTU TCP instance
# $address - Modbus register address
# $type - Register type (3 = DWord, 7 = Real)
# $profile - Variable profile name
function createSensor($category, $pos, $name, $modbus, $address, $type, $profile) {
$sensor = IPS_CreateInstance(MODBUS_ADDRESS);
IPS_SetName($sensor, $name);
IPS_SetHidden($sensor, true);
IPS_SetParent($sensor, $category);
IPS_ConnectInstance($sensor, $modbus);
Modbus_SetType($sensor, $type);
IPS_SetProperty($sensor, 'ReadAddress', $address);
IPS_ApplyChanges($sensor);
$variable = IPS_GetVariableIDByName('Value', $sensor);
IPS_SetVariableCustomProfile($variable, $profile);
IPS_SetVariableCustomAction($variable, 1);
$archive = getArchiveInstance();
AC_SetLoggingStatus($archive, $variable, true);
$link = IPS_CreateLink();
IPS_SetName($link, $name);
IPS_SetParent($link, $category);
IPS_SetPosition($link, $pos);
IPS_SetLinkChildID($link, $variable);
}
# Create category and sensor instances for Mains meter
# $category - Parent category
# $pos - Position in parent category
# $modbus - ModBus RTU TCP instance
function createMains($category, $pos, $modbus) {
$base = 0x3000;
$cat = createCategory('Mains', $category, $pos);
$pos = 0;
createSensor($cat, $pos++, 'RMS Voltage', $modbus, $base + 0x08, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L1-L2 RMS Voltage', $modbus, $base + 0x48, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L2-L3 RMS Voltage', $modbus, $base + 0x78, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L3-L1 RMS Voltage', $modbus, $base + 0xa8, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'RMS Current', $modbus, $base + 0x0a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L1 RMS Current', $modbus, $base + 0x4a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L2 RMS Current', $modbus, $base + 0x7a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L3 RMS Current', $modbus, $base + 0xaa, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'Current Unbalance', $modbus, $base + 0x10, 7, 'RaritanCurrentUnbalance');
createSensor($cat, $pos++, 'Active Power', $modbus, $base + 0x12, 7, 'RaritanActivePower');
createSensor($cat, $pos++, 'Apparent Power', $modbus, $base + 0x14, 7, 'RaritanApparentPower');
createSensor($cat, $pos++, 'Power Factor', $modbus, $base + 0x16, 7, 'RaritanPowerFactor');
createSensor($cat, $pos++, 'Active Energy', $modbus, $base + 0x1a, 3, 'RaritanActiveEnergy');
createSensor($cat, $pos++, 'Line Frequency', $modbus, $base + 0x22, 7, 'RaritanLineFrequency');
}
# Create category and sensor instances for a single-phase branch circuit
# $category - Parent category
# $pos - Position in parent category
# $modbus - ModBus RTU TCP instance
# $branch - Branch number
# $i - Outlet block index in Modbus register set
function create1PhaseBranch($category, $pos, $modbus, $branch, $i) {
$name = "Branch $branch";
$base = 0x8000 + $i * 0x100;
$cat = createCategory($name, $category, $pos);
$pos = 0;
createSensor($cat, $pos++, 'RMS Voltage', $modbus, $base + 0x08, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'RMS Current', $modbus, $base + 0x0a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'Active Power', $modbus, $base + 0x12, 7, 'RaritanActivePower');
createSensor($cat, $pos++, 'Apparent Power', $modbus, $base + 0x14, 7, 'RaritanApparentPower');
createSensor($cat, $pos++, 'Power Factor', $modbus, $base + 0x16, 7, 'RaritanPowerFactor');
createSensor($cat, $pos++, 'Active Energy', $modbus, $base + 0x1a, 3, 'RaritanActiveEnergy');
createSensor($cat, $pos++, 'Line Frequency', $modbus, $base + 0x22, 7, 'RaritanLineFrequency');
}
# Create category and sensor instances for a three-phsae branch circuit
# $category - Parent category
# $pos - Position in parent category
# $modbus - ModBus RTU TCP instance
# $branch - Number of first branch channel
# $i - Outlet block index in Modbus register set
function create3PhaseBranch($category, $pos, $modbus, $branch, $i) {
$name = 'Branch ' . $branch . '-' . ($branch + 2);
$base = 0x8000 + $i * 0x100;
$cat = createCategory($name, $category, $pos);
$pos = 0;
createSensor($cat, $pos++, 'RMS Voltage', $modbus, $base + 0x08, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L1-L2 RMS Voltage', $modbus, $base + 0x48, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L2-L3 RMS Voltage', $modbus, $base + 0x78, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'L3-L1 RMS Voltage', $modbus, $base + 0xa8, 7, 'RaritanVoltage');
createSensor($cat, $pos++, 'RMS Current', $modbus, $base + 0x0a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L1 RMS Current', $modbus, $base + 0x4a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L2 RMS Current', $modbus, $base + 0x7a, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'L3 RMS Current', $modbus, $base + 0xaa, 7, 'RaritanCurrent');
createSensor($cat, $pos++, 'Current Unbalance', $modbus, $base + 0x10, 7, 'RaritanCurrentUnbalance');
createSensor($cat, $pos++, 'Active Power', $modbus, $base + 0x12, 7, 'RaritanActivePower');
createSensor($cat, $pos++, 'Apparent Power', $modbus, $base + 0x14, 7, 'RaritanApparentPower');
createSensor($cat, $pos++, 'Power Factor', $modbus, $base + 0x16, 7, 'RaritanPowerFactor');
createSensor($cat, $pos++, 'Active Energy', $modbus, $base + 0x1a, 3, 'RaritanActiveEnergy');
createSensor($cat, $pos++, 'Line Frequency', $modbus, $base + 0x22, 7, 'RaritanLineFrequency');
}
# Create categories and sensor instances for all branch circuits
# $category - Parent category
# $pos - Position in parent category
# $modbus - ModBus RTU TCP instance
function createBranches($category, $pos, $modbus) {
$outlet = 0;
global $circuits;
for ($i = 0; $i < count($circuits); $i++) {
$circuit_config = $circuits[$i];
if ($circuit_config == 1) {
create1PhaseBranch($category, $pos++, $modbus, 3*$i + 1, $outlet++);
create1PhaseBranch($category, $pos++, $modbus, 3*$i + 2, $outlet++);
create1PhaseBranch($category, $pos++, $modbus, 3*$i + 3, $outlet++);
} elseif ($circuit_config == 3) {
create3PhaseBranch($category, $pos++, $modbus, 3*$i + 1, $outlet++);
} else {
trigger_error("Invalid configuration for branch circuit $i", E_USER_ERROR);
}
}
}
# main function
createProfiles();
$cat_root = createCategory($name);
$modbus = createModbus($host, $port, $name);
createMains($cat_root, 0, $modbus);
createBranches($cat_root, 1, $modbus);
?>