heizung/app/Console/Commands/MqttMock.php

74 lines
2.5 KiB
PHP
Raw Normal View History

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use PhpMqtt\Client\ConnectionSettings;
use PhpMqtt\Client\MqttClient;
class MqttMock extends Command
{
protected $signature = 'mqtt:mock
{--device=eltern : Device slug}
{--interval=10 : Seconds between publishes}
{--duration=0 : Stop after N seconds (0 = forever)}';
protected $description = 'Publish mock heating data to MQTT';
public function handle(): int
{
$c = $this->makeClient();
$dev = $this->option('device');
$iv = (int) $this->option('interval');
$dur = (int) $this->option('duration');
$end = $dur > 0 ? time()+$dur : null;
$this->info("Mock $dev every {$iv}s");
while (true) {
if ($end && time() >= $end) break;
[$b,$t] = $this->generate();
$c->publish("ems-esp/$dev/boiler", json_encode($b), 0);
$c->publish("ems-esp/$dev/thermostat", json_encode($t), 0);
$this->line(now()->format('H:i:s')." flow={$b['curflowtemp']} burn={$b['burngas']} ist={$t['hc1_currtemp']}");
sleep($iv);
}
$c->disconnect();
return 0;
}
private function generate(): array
{
$h = (float)now()->format('G') + (int)now()->format('i')/60.0;
$heat = ($h >= 6 && $h < 22);
$burn = $heat && (rand(0,100) < 60) ? 1 : 0;
$out = 5 + 8*sin(($h-3)/24*2*M_PI) + rand(-10,10)/10;
$set = $heat ? 21.0 : 18.0;
$ft = $burn ? 55 + (15-$out)*0.8 : 38;
return [[
'curflowtemp'=>round($ft + rand(-15,15)/10,1),
'selflowtemp'=>round($ft,1),
'burngas'=>$burn,
'wwseltemp'=>55,
'wwcurtemp'=>round(55-rand(0,30)/10,1),
'outdoortemp'=>round($out,1),
],[
'hc1_seltemp'=>$set,
'hc1_currtemp'=>round($set+rand(-6,6)/10,1),
'hc1_mode'=>$heat?'auto':'night',
]];
}
private function makeClient(): MqttClient
{
$c = new MqttClient(env('MQTT_HOST'), (int)env('MQTT_PORT',8883), 'heizung-mock');
$cs = (new ConnectionSettings)
->setUsername(env('MQTT_MOCK_USERNAME'))
->setPassword(env('MQTT_MOCK_PASSWORD'))
->setUseTls(true)
->setTlsVerifyPeer(true)
->setTlsVerifyPeerName(true)
->setTlsCertificateAuthorityPath(env('MQTT_CA_PATH','/etc/ssl/certs'))
->setKeepAliveInterval(60)
->setConnectTimeout(10);
$c->connect($cs, true);
return $c;
}
}