ReadCommand.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Jobs\SendDataJob;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Facades\Cache;
  6. use Illuminate\Support\Facades\Redis;
  7. class ReadCommand extends Command
  8. {
  9. /**
  10. * The name and signature of the console command.
  11. *
  12. * @var string
  13. */
  14. protected $signature = 'command:readTXT';
  15. /**
  16. * The console command description.
  17. *
  18. * @var string
  19. */
  20. protected $description = '读取文件';
  21. /**
  22. * Create a new command instance.
  23. *
  24. * @return void
  25. */
  26. public function __construct()
  27. {
  28. parent::__construct();
  29. }
  30. /**
  31. * Execute the console command.
  32. *
  33. * @return mixed
  34. */
  35. public function handle()
  36. {
  37. // $this->readTxtForData();
  38. $this->tcpServer();
  39. $this->info('Your command executed!');
  40. }
  41. //读取数据
  42. public function readTxtForData()
  43. {
  44. $directory = env('PROCESS_DIR',null);
  45. if(! $directory) {
  46. echo '未找到日志文件位置,请确认工具运行位置,再进行配置!';die;
  47. }
  48. $newLogFile = storage_path().'/app/public/record_device.txt';
  49. // $positionFile = storage_path().'/app/public/position_device.txt';
  50. date_default_timezone_set("PRC");
  51. $key = date("Y-m-d",time());
  52. $position = Cache::get($key);
  53. // 读取上次记录的位置
  54. $lastPosition = 0;
  55. if ($position) $lastPosition = $position;
  56. // if (file_exists($positionFile)) {
  57. // $lastPosition = intval(file_get_contents($positionFile));
  58. // }
  59. // 持续监视日志文件的变化
  60. while (true) {
  61. $key = date("Y-m-d",time());
  62. //日志源 文件位置
  63. $logFile = $directory . "/TesttoolLog" . $key . '.log';
  64. // 检查文件是否有更新
  65. clearstatcache(true, $logFile);
  66. $currentFileSize = filesize($logFile);
  67. echo "当前指针位置:$currentFileSize 上一次指针位置:$lastPosition \n";
  68. if ($currentFileSize > $lastPosition) {
  69. // 打开原始日志文件和新的日志文件
  70. $fileHandle = fopen($logFile, 'r');
  71. $newFileHandle = fopen($newLogFile, 'a'); // 使用追加模式打开新的日志文件
  72. // 移动文件指针到上次记录的位置
  73. fseek($fileHandle, $lastPosition);
  74. // 逐行读取并处理新增内容
  75. $read_data = [];
  76. while (($line = fgets($fileHandle)) !== false) {
  77. // 提取Tag数字
  78. $pattern = '/Tag:(\d+)/';
  79. preg_match($pattern, $line, $matches);
  80. if (isset($matches[1])) {
  81. $tagNumber = $matches[1];
  82. echo "接收到的数据:" . $tagNumber . "\n";
  83. $read_data[] = $tagNumber;
  84. // 将Tag数字写入新的日志文件
  85. fwrite($newFileHandle, $tagNumber . PHP_EOL);
  86. }
  87. }
  88. if(! empty($read_data)) {
  89. $this->sendData($read_data);
  90. echo '发送成功---!' . "\n";
  91. }
  92. // 获取新的位置并更新位置文件
  93. $lastPosition = ftell($fileHandle);
  94. Cache::put($key,$lastPosition,86400);
  95. // file_put_contents($positionFile, $lastPosition);
  96. // 关闭文件句柄
  97. fclose($fileHandle);
  98. fclose($newFileHandle);
  99. } else {
  100. echo '暂无新数据...' . "\n";
  101. // 在下一次检查之前休眠一段时间
  102. sleep(2);
  103. }
  104. }
  105. }
  106. public function sendData($data){
  107. $url = env('CLOUD_ADDRESS',null);
  108. if(empty($url)) return;
  109. $curl = curl_init();
  110. curl_setopt_array($curl, array(
  111. CURLOPT_URL => $url,
  112. CURLOPT_RETURNTRANSFER => true,
  113. CURLOPT_ENCODING => '',
  114. CURLOPT_MAXREDIRS => 10,
  115. CURLOPT_TIMEOUT => 0,
  116. CURLOPT_FOLLOWLOCATION => true,
  117. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  118. CURLOPT_CUSTOMREQUEST => 'POST',
  119. CURLOPT_POSTFIELDS => $data,
  120. ));
  121. $response = curl_exec($curl);
  122. curl_close($curl);
  123. }
  124. public function tcpServer(){
  125. $host = env('HOST_TCP',null); // 主机地址 $_SERVER['REMOTE_ADDR']; 局域网内ip地址
  126. $port = env('HOST_PORT',null); // 端口号
  127. // 创建一个TCP socket
  128. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  129. // 绑定到指定的主机和端口
  130. socket_bind($socket, $host, $port);
  131. // 监听连接
  132. socket_listen($socket);
  133. // 初始内存使用量
  134. $initialMemoryUsage = memory_get_usage();
  135. echo date("Y-m-d H:i:s") . "服务器已启动\n";
  136. file_put_contents('C:\Users\Administrator\Desktop\record.txt',date("Y-m-d H:i:s") . "服务器已启动".PHP_EOL,8);
  137. while (true) {
  138. // 接受连接请求并创建新的套接字
  139. $clientSocket = socket_accept($socket);
  140. if ($clientSocket === false) {
  141. // 错误处理
  142. $error = socket_strerror(socket_last_error($socket));
  143. echo "接受连接请求失败:{$error}\n";
  144. continue; // 继续下一次循环
  145. }
  146. try {
  147. // 读取客户端发送的数据
  148. $data = socket_read($clientSocket, 1024);
  149. // 其他操作...
  150. } catch (Exception $e) {
  151. // 异常处理
  152. echo date("Y-m-d H:i:s") . "捕获到异常:{$e->getMessage()}\n";
  153. continue; // 继续下一次循环
  154. }
  155. // file_put_contents('C:\Users\Administrator\Desktop\record2.txt',$data .PHP_EOL,8);
  156. $this->byteParsing3($data);
  157. // 发送响应给客户端
  158. // $response = "服务器已接收到您的消息:" . $data;
  159. // socket_write($clientSocket, $response, strlen($response));
  160. $currentMemoryUsage = memory_get_usage();
  161. $memoryDiff = $currentMemoryUsage - $initialMemoryUsage;
  162. echo "内存使用量变化:" . $memoryDiff . " 字节\n";
  163. $initialMemoryUsage = $currentMemoryUsage;
  164. // 关闭当前连接的套接字
  165. socket_close($clientSocket);
  166. gc_collect_cycles();
  167. sleep(5);
  168. }
  169. // 关闭服务器套接字
  170. socket_close($socket);
  171. }
  172. public function byteParsing2($data){
  173. $frame = $data;
  174. // 提取字段值
  175. $frameHeader = bin2hex(substr($frame, 0, 2));
  176. $frameLength = unpack('v', substr($frame, 2, 2))[1];
  177. $frameSequence = unpack('v', substr($frame, 4, 2))[1];
  178. $port = ord(substr($frame, 6, 1));
  179. $communicationType = unpack('v', substr($frame, 7, 2))[1];
  180. $payload = substr($frame, 9, $frameLength - 8);
  181. $checksum = ord(substr($frame, -3, 1));
  182. $frameTail = bin2hex(substr($frame, -2));
  183. $payloadBytes = substr($frame, 9, 4); // 假设帧载荷在通信帧中的偏移量为9,并且长度为4个字节
  184. // 将4个字节转换为无符号整数(根据您的数据编码方式确定是否需要使用符号整数)
  185. $payloadValue = unpack('N', $payloadBytes)[1];
  186. echo "zhen" . $payloadValue . "\n";
  187. $payloadHex = sprintf('%08X', $payloadValue);
  188. echo "帧载荷值: $payloadHex\n";
  189. // 打印字段值
  190. echo "帧头: $frameHeader\n";
  191. echo "帧长度: $frameLength\n";
  192. echo "帧序号: $frameSequence\n";
  193. echo "端口: $port\n";
  194. echo "通信类型: $communicationType\n";
  195. echo "帧载荷: $payload\n";
  196. echo "校验和: $checksum\n";
  197. echo "帧尾: $frameTail\n";
  198. }
  199. public function byteParsing($data){
  200. // 接收到的TCP数据(以字节形式表示)
  201. $tcpData = $data;
  202. // 解析源端口和目标端口
  203. $sourcePort = unpack('n', substr($tcpData, 0, 2))[1];
  204. $destinationPort = unpack('n', substr($tcpData, 2, 2))[1];
  205. // 解析其他TCP头部字段,解析序列号
  206. $sequenceNumber = unpack('N', substr($tcpData, 4, 4))[1];
  207. // 获取TCP头部长度(通过读取数据偏移计算得出)
  208. $dataOffset = ord(substr($tcpData, 12, 1)) >> 4;
  209. $headerLength = $dataOffset * 4;
  210. // 提取数据部分
  211. $data = substr($tcpData, $headerLength);
  212. // 处理数据部分中的控制字符
  213. $data = $this->removeControlCharacters($data);
  214. // 打印解析结果
  215. echo "源端口: $sourcePort\n";
  216. echo "目标端口: $destinationPort\n";
  217. echo "序列号: $sequenceNumber\n";
  218. if(! empty($data)){
  219. echo "数据: $data\n";
  220. }
  221. }
  222. // 去除控制字符的函数
  223. function removeControlCharacters($string) {
  224. $controlChars = array(
  225. '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', // 去除 ASCII 控制字符
  226. // '/\xEF\xBF\xBD/u' // 去除 UTF-8 中的替代字符
  227. );
  228. return preg_replace($controlChars, '', $string);
  229. }
  230. public function readTxt(){
  231. $directory = env('PROCESS_DIR',null);
  232. $directory = 'C:\Users\Administrator\Desktop\\'; // 替换为你的文件所在目录路径
  233. $currentDate = date('Y-m-d'); // 当前日期
  234. $file = $directory . "TesttoolLog" . $currentDate . '.log'; // 拼接文件路径和文件名
  235. $lastModified = filemtime($file); // 获取文件最后修改时间
  236. while (true) {
  237. clearstatcache(); // 清除文件状态缓存
  238. $currentDate = date('Y-m-d'); // 获取当前日期
  239. $currentFile = $directory . "TesttoolLog" . $currentDate . '.log'; // 当前日期对应的文件路径和文件名
  240. if ($file !== $currentFile) {
  241. // 文件已切换,更新文件路径和最后修改时间
  242. $file = $currentFile;
  243. $lastModified = filemtime($file);
  244. }
  245. $currentModified = filemtime($file); // 获取当前文件最后修改时间
  246. if ($currentModified > $lastModified) {
  247. // 文件已被修改,读取新增内容
  248. $handle = fopen($file, 'r');
  249. fseek($handle, -1, SEEK_END); // 定位到文件末尾前两个字节
  250. $data = fread($handle, 2); // 读取新增内容
  251. fclose($handle);
  252. // 处理新增内容
  253. // ...
  254. // 示例:打印新增内容
  255. echo $data;
  256. $lastModified = $currentModified; // 更新最后修改时间
  257. }
  258. sleep(1); // 睡眠一段时间后再次检查文件是否被修改
  259. }
  260. }
  261. public function byteParsing3($data){
  262. $hexData = bin2hex($data);
  263. $hexData = str_replace(' ', '', $hexData);
  264. $toReplace = array("a6a8001300000a00010101001708120012000103b5a5a7", "a6a8000c00000a0003120001037da5a7");
  265. $result = str_replace($toReplace, "", $hexData);
  266. // echo "原数据:" . $hexData . PHP_EOL;
  267. // $memoryUsage = memory_get_usage();
  268. // echo "当前脚本占用的内存量:".$memoryUsage." 字节" . "\n";
  269. //
  270. // $memoryUsage = memory_get_peak_usage();
  271. // echo "PHP程序总内存使用量:" . $memoryUsage . " 字节" . "\n";
  272. if($result){
  273. $last38Chars = substr($result, -38, 32);
  274. echo "替换后:" . $last38Chars . PHP_EOL;
  275. file_put_contents('C:\Users\Administrator\Desktop\record.txt',$last38Chars.PHP_EOL,8);
  276. if(! empty($last38Chars)) {
  277. $this->sendData([$last38Chars]);
  278. echo '发送成功---!' . "\n";
  279. }
  280. }
  281. }
  282. }