no message

This commit is contained in:
2025-11-25 07:27:24 +01:00
parent 10b53b2463
commit d82e86e556
5 changed files with 74 additions and 263 deletions

View File

View File

@@ -1,9 +0,0 @@
{
"elements": [
{
"type": "ValidationTextBox",
"name": "DeviceID",
"caption": "Device ID"
}
]
}

View File

@@ -1,17 +0,0 @@
{
"id": "{ED0ED0AC-3843-0888-DF27-FA488A5BCEF3}",
"name": "Int_VGT",
"type": 3,
"vendor": "Belevo",
"aliases": [
"VGT MQTT-Gateway"
],
"prefix": "VGT",
"parentRequirements": [
"{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}"
],
"childRequirements": [],
"implemented": [
"{7F7632D9-FA40-4F38-8DEA-C83CD4325A32}"
]
}

View File

@@ -1,237 +0,0 @@
<?php
declare(strict_types=1);
class Int_VGT extends IPSModule
{
private bool $Subscribed = false;
public function Create()
{
parent::Create();
$this->RegisterPropertyString('DeviceID', '');
/** -------------------------------------------
* STATUS Variablen (schreibbar)
* ------------------------------------------*/
$this->RegisterVariableInteger('PowerProduction', 'Power Production', '', 10);
$this->EnableAction('PowerProduction');
$this->RegisterVariableBoolean('IsReady', 'Is Ready', '', 11);
$this->EnableAction('IsReady');
$this->RegisterVariableBoolean('IsRunning', 'Is Running', '', 12);
$this->EnableAction('IsRunning');
$this->RegisterVariableInteger('StateOfCharge', 'State of Charge', '', 13);
$this->EnableAction('StateOfCharge');
$this->RegisterVariableInteger('MinSOC', 'Min SOC', '', 14);
$this->EnableAction('MinSOC');
$this->RegisterVariableInteger('MaxSOC', 'Max SOC', '', 15);
$this->EnableAction('MaxSOC');
/** -------------------------------------------
* REMOTE CONTROL (read-only)
* ------------------------------------------*/
$this->RegisterVariableInteger('PowerSetpoint', 'Power Setpoint', '', 20);
$this->RegisterVariableString('Strategy', 'Strategy', '', 21);
// Debug
$this->RegisterVariableString('RemoteControlPayload', 'Remote Control Payload', '', 30);
/** -------------------------------------------
* FEEDBACK REQUEST (read-only)
* ------------------------------------------*/
$this->RegisterVariableString('FeedbackRequestPayload', 'Feedback Request Payload', '', 40);
/** -------------------------------------------
* MQTT verbinden
* ------------------------------------------*/
$this->ConnectParent('{C6D2AEB3-6E1F-4B2E-8E69-3A1A00246850}');
}
public function ApplyChanges()
{
parent::ApplyChanges();
$this->ConnectParent('{C6D2AEB3-6E1F-4B2E-8E69-3A1A00246850}');
// Beim Start niemals subscriben erst wenn Daten fließen oder Parent aktiv wird
$this->Subscribed = false;
// Parent-Status überwachen für Re-Subscribe
$this->RegisterMessage($this->InstanceID, IM_CHANGESTATUS);
$parent = @IPS_GetInstance($this->InstanceID)['ConnectionID'] ?? 0;
if ($parent > 0 && IPS_InstanceExists($parent)) {
$this->RegisterMessage($parent, IM_CHANGESTATUS);
}
}
/* ---------------------------------------------------------
* MESSAGE SINK PARENT STATUS
* ---------------------------------------------------------*/
public function MessageSink($TimeStamp, $SenderID, $Message, $Data)
{
if ($Message === IM_CHANGESTATUS) {
// Eigene Instanz aktiv
if ($SenderID === $this->InstanceID && ($Data[0] ?? 0) === IS_ACTIVE) {
$this->TrySubscribe();
return;
}
// Parent aktiv
$parent = @IPS_GetInstance($this->InstanceID)['ConnectionID'] ?? 0;
if ($parent > 0 && $SenderID === $parent && ($Data[0] ?? 0) === IS_ACTIVE) {
$this->TrySubscribe();
return;
}
}
}
/* ---------------------------------------------------------
* SAFE SEND TO PARENT
* ---------------------------------------------------------*/
private function SafeSendToParent(array $packet)
{
$parent = @IPS_GetInstance($this->InstanceID)['ConnectionID'] ?? 0;
if ($parent === 0 || !IPS_InstanceExists($parent)) {
return;
}
if (IPS_GetInstance($parent)['InstanceStatus'] !== IS_ACTIVE) {
return;
}
@ $this->SendDataToParent(json_encode($packet));
}
/* ---------------------------------------------------------
* Subscribe erst ausführen, wenn Parent sicher aktiv ist
* ---------------------------------------------------------*/
private function TrySubscribe()
{
if ($this->Subscribed) {
return;
}
$device = $this->ReadPropertyString('DeviceID');
if ($device === '') {
return;
}
$this->Subscribed = true;
$this->Subscribe("feedback-request/$device");
$this->Subscribe("remote-control-request/$device");
}
/* ---------------------------------------------------------
* REQUEST ACTION
* ---------------------------------------------------------*/
public function RequestAction($Ident, $Value)
{
$this->SetValue($Ident, $Value);
}
/* ---------------------------------------------------------
* SUBSCRIBE (safe)
* ---------------------------------------------------------*/
private function Subscribe(string $topic): void
{
$this->SafeSendToParent([
'DataID' => '{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}',
'PacketType' => 8,
'QualityOfService' => 0,
'Retain' => false,
'Topic' => $topic,
'Payload' => ''
]);
}
/* ---------------------------------------------------------
* PUBLISH (safe)
* ---------------------------------------------------------*/
private function Publish(string $topic, string $payload): void
{
$this->SafeSendToParent([
'DataID' => '{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}',
'PacketType' => 3,
'QualityOfService' => 0,
'Retain' => false,
'Topic' => $topic,
'Payload' => $payload
]);
}
/* ---------------------------------------------------------
* RECEIVE DATA
* ---------------------------------------------------------*/
public function ReceiveData($JSONString)
{
// Beim ersten Paket: subscriben
$this->TrySubscribe();
$data = json_decode($JSONString, true);
if (!is_array($data)) return;
$topic = $data['Topic'] ?? '';
$payload = $data['Payload'] ?? '';
$device = $this->ReadPropertyString('DeviceID');
/* ---------------------------------------------------------
* 1⃣ FEEDBACK REQUEST
* ---------------------------------------------------------*/
if ($topic === "feedback-request/$device") {
$this->SetValue('FeedbackRequestPayload', $payload);
$json = json_decode($payload, true);
if (!is_array($json)) {
$json = [];
}
$response = array_merge($json, [
"power_production" => $this->GetValue('PowerProduction'),
"is_ready" => $this->GetValue('IsReady'),
"is_running" => $this->GetValue('IsRunning'),
"state_of_charge" => $this->GetValue('StateOfCharge'),
"min_soc" => $this->GetValue('MinSOC'),
"max_soc" => $this->GetValue('MaxSOC')
]);
$this->Publish("feedback-response/$device", json_encode($response));
return;
}
/* ---------------------------------------------------------
* 2⃣ REMOTE CONTROL REQUEST
* ---------------------------------------------------------*/
if ($topic === "remote-control-request/$device") {
$this->SetValue('RemoteControlPayload', $payload);
$json = json_decode($payload, true);
if (is_array($json)) {
if (array_key_exists('power_setpoint', $json)) {
$this->SetValue('PowerSetpoint', (int)$json['power_setpoint']);
}
if (array_key_exists('strategy', $json)) {
$this->SetValue('Strategy', (string)$json['strategy']);
}
}
$this->Publish("remote-control-response/$device", $payload);
return;
}
}
}
?>

View File

@@ -4,6 +4,80 @@
"type": "ValidationTextBox",
"name": "DeviceID",
"caption": "Device ID"
},
{
"type": "Label",
"caption": "Variablen zuordnen"
},
{
"type": "SelectVariable",
"name": "VarPowerProduction",
"caption": "Power Production Variable (Float)"
},
{
"type": "SelectVariable",
"name": "VarStateOfCharge",
"caption": "State of Charge Variable (Float/Integer)"
},
{
"type": "SelectVariable",
"name": "VarIsRunning",
"caption": "Is Running Variable (Boolean)"
},
{
"type": "Label",
"caption": "SOC Bereich"
},
{
"type": "NumberSpinner",
"name": "MinSOC",
"caption": "Min SOC",
"minimum": 0,
"maximum": 100
},
{
"type": "NumberSpinner",
"name": "MaxSOC",
"caption": "Max SOC",
"minimum": 0,
"maximum": 100
},
{
"type": "Label",
"caption": "Abonnierte Topics"
},
{
"type": "Label",
"caption": "feedback-request/<device>"
},
{
"type": "Label",
"caption": "remote-control-request/<device>"
},
{
"type": "Label",
"caption": "Debug"
},
{
"type": "Label",
"caption": "Alle empfangenen MQTT-Daten werden in den Debug-Log geschrieben."
}
],
"status": [
{
"code": 101,
"icon": "spinner",
"caption": "Verbindung wird hergestellt..."
},
{
"code": 102,
"icon": "ok",
"caption": "Bereit"
},
{
"code": 200,
"icon": "error",
"caption": "Fehlerhafte Konfiguration"
}
]
}