Workerman本身不直接支持LED大屏控制卡通信,因其需严格遵循厂商私有二进制协议(如诺瓦JSON over TCP、灵星雨纯二进制),须自行实现指令拼包、编码转换(UTF-8→GB2312)、CRC校验及socket通信,不可用Worker::sendToClient推送。

Workerman 本身不直接支持 LED 大屏控制卡通信,因为绝大多数 LED 控制卡(如诺瓦、灵星雨、凯视达等)使用私有二进制协议,走 TCP/UDP 长连接或 HTTP 指令,且需严格遵循厂商定义的帧结构、校验方式和认证流程。你不能把 Workerman 当作“即插即用”的 LED 驱动层 —— 它只是网络服务容器,真正对接控制卡,得靠你自己实现协议解析与指令封装。
onMessage 收到通知后怎么发给 LED 控制卡?
Workerman 的 onMessage 只负责收前端(如 Web 页面、管理后台)发来的滚动文本,它不处理硬件。你要在收到消息后,主动发起一次对控制卡的通信:
- 控制卡通常监听固定 IP + 端口(如
192.168.1.100:5232),协议多为 TCP(少数 UDP) - 必须按厂商文档拼接二进制指令包(含头帧、设备 ID、区域号、字体大小、颜色、滚动速度、UTF-8 转 GB2312/GBK 编码、CRC16 校验等)
- 建议用
stream_socket_client或fsockopen发送,不要用file_get_contents或 cURL
示例关键逻辑:
$socket = stream_socket_client("tcp://192.168.1.100:5232", $errno, $errstr, 3);
if ($socket) {
$cmd = pack('H*', 'aa000100000000000000000000000000') . iconv('UTF-8', 'GB2312//IGNORE', $text) . "\x00";
$cmd .= pack('n', crc16($cmd)); // 假设校验在末尾
fwrite($socket, $cmd);
fclose($socket);
}
注意:不同厂商指令结构差异极大,诺瓦用 JSON over TCP,灵星雨用纯二进制流,凯视达可能要求先登录再发屏显指令 —— 不查对应 SDK 或《通信协议手册》,发出去就是乱码或无响应。
为什么不能直接用 Worker::sendToClient 推送?
Worker::sendToClient 是 Workerman 内部用于 WebSocket/TCP 连接池广播的 API,只对它自己管理的客户端连接有效。LED 控制卡不是你的 $worker->connections 之一,它不会连你的 websocket:// 或 tcp:// 服务,也不会响应 send() 调用。强行调用只会报错:Call to undefined method Worker::sendToClient() 或静默失败。
你必须把它当作一个外部 TCP 服务端来对待:每次推送,都新建 socket、发包、关连接(或复用长连接,但需自行维护心跳和重连)。
怎么避免滚动文字乱码或截断?
核心就两点:编码 + 包长限制
- LED 控制卡普遍不支持 UTF-8,必须转成
GB2312或GBK;用iconv('UTF-8', 'GB2312//IGNORE', $text),别用mb_convert_encoding(默认行为不一致) - 单条指令包总长度常有限制(如诺瓦常见 ≤ 1024 字节),超长会丢弃后半段;需提前截断或分包发送
- 中文字符在 GB2312 下占 2 字节,但控制卡实际显示宽度还受字体点阵影响(比如 16×16 字库下,1 个中文 ≈ 2 个英文宽度),滚动效果要实测调整字数
另外,部分控制卡要求文本末尾补 \x00 结束符,缺了就不刷新画面。
LED 控制卡协议极其“硬核”:没有统一标准、文档常滞后、调试靠抓包+试错。Workerman 只是帮你把“人发来的通知”快速传下去的管道,真正的协议适配、异常重试、断线恢复、多卡轮询,全得你自己补全。别指望 composer require 一个包就搞定。

















