Files
2026-08-02 02:23:18 +08:00

148 lines
4.7 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\process;
use app\service\AudioService;
use Workerman\Timer as WorkermanTimer;
use Workerman\Worker;
class Timer
{
private const VAR_POS = 28;
private const VAR_OFFSET = 0x0F;
private const HEX_DATA = [
0x55, 0xAA, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC1,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
0x00, 0x00, 0x09, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0D,
0x0A
];
private int $port;
private int $maxValue;
private float $intervalSec;
private array $texts = [];
private array $targets = []; // 目标列表 [['ip'=>'...','port'=>...], ...]
private AudioService $audio;
public function onWorkerStart(Worker $worker): void
{
$this->port = (int)(getenv('TIMER_PORT') ?: 10000);
$this->maxValue = (int)(getenv('TIMER_MAX') ?: 6);
$this->intervalSec = (float)(getenv('TIMER_INTERVAL') ?: 1);
$this->loadTexts();
$this->targets = $this->loadIps();
$this->audio = new AudioService();
echo "Timer process is running.\n";
echo "目标: ";
foreach ($this->targets as $t) {
echo "{$t['ip']}:{$t['port']} ";
}
echo "\n最大值: {$this->maxValue}, 间隔: {$this->intervalSec}s\n";
$value = 1;
$timerCallback = function () use (&$value) {
$text = $this->texts[$value] ?? "当前: {$value}";
$okImg = $this->sendImage($value);
$status = $okImg ? '图✓' : '图✗';
echo "\r[{$value}] {$status} {$text}";
$okAudio = $this->audio->sendText($text);
$status .= ' ' . ($okAudio ? '音✓' : '音✗');
echo "\r[{$value}] {$status} {$text}\n";
$value = $value >= $this->maxValue ? 1 : $value + 1;
};
// 立即执行一次,再定时
$timerCallback();
WorkermanTimer::add($this->intervalSec, $timerCallback);
}
/**
* 加载目标 IP 列表
* 优先检查 TIMER_IPS 环境变量(逗号分隔,可带端口如 192.168.1.1:10001
* 否则回退到单个 TIMER_IP + TIMER_PORT
*/
private function loadIps(): array
{
$targets = [];
$ipsEnv = getenv('TIMER_IPS');
if ($ipsEnv !== false && trim($ipsEnv) !== '') {
// 多 IP 模式
$parts = explode(',', $ipsEnv);
foreach ($parts as $part) {
$part = trim($part);
if ($part === '') continue;
if (strpos($part, ':') !== false) {
[$ip, $portStr] = explode(':', $part, 2);
$targets[] = [
'ip' => trim($ip),
'port' => (int)trim($portStr)
];
} else {
$targets[] = [
'ip' => $part,
'port' => $this->port
];
}
}
} else {
// 兼容单 IP 旧配置
$ip = getenv('TIMER_IP') ?: '192.168.42.1';
$targets[] = [
'ip' => $ip,
'port' => $this->port
];
}
return $targets;
}
/**
* 向所有目标发送 HEX 数据包
* @return bool 全部发送成功返回 true,任一失败返回 false
*/
private function sendImage(int $variable): bool
{
$data = self::HEX_DATA;
$data[self::VAR_POS] = ($variable + self::VAR_OFFSET) & 0xFF;
$packedData = pack('C*', ...$data);
$allSuccess = true;
foreach ($this->targets as $target) {
try {
$socket = @fsockopen($target['ip'], $target['port'], $errno, $errstr, 5);
echo "\r图> 尝试连接 [{$target['ip']}:{$target['port']}]";
if (!$socket) {
echo "\r图> 连接失败 [{$target['ip']}:{$target['port']}]: {$errstr} ({$errno})\n";
$allSuccess = false;
continue;
}
echo "\r图> 已连接 [{$target['ip']}:{$target['port']}]";
fwrite($socket, $packedData);
fflush($socket);
fclose($socket);
}catch (\Exception $exception){
echo "发送数据失败 [{$target['ip']}:{$target['port']}]: {$exception->getMessage()}\n";
$allSuccess = false;
}
}
return $allSuccess;
}
private function loadTexts(): void
{
for ($i = 1; $i <= $this->maxValue; $i++) {
$t = getenv('TIMER_TEXT_' . $i);
if ($t !== false && $t !== '') {
$this->texts[$i] = $t;
}
}
}
}