1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Posprint\Extras; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Serial port control class |
7
|
|
|
* |
8
|
|
|
* Refactoring from original, https://github.com/Xowap/PHP-Serial, to meet PSR standards |
9
|
|
|
* and propose improvements and fixes to the fact that the original is not actively |
10
|
|
|
* maintained for many years. |
11
|
|
|
* by Roberto L. Machado <linux dot rlm at gmail dot com> |
12
|
|
|
* |
13
|
|
|
* IMPORTANT: check and adjust permissions for serial port access by server user like www-data |
14
|
|
|
* |
15
|
|
|
* @author Rémy Sanchez <[email protected]> |
16
|
|
|
* @author Rizwan Kassim <[email protected]> |
17
|
|
|
* @thanks Aurélien Derouineau for finding how to open serial ports with windows |
18
|
|
|
* @thanks Alec Avedisyan for help and testing with reading |
19
|
|
|
* @thanks Jim Wright for OSX cleanup/fixes. |
20
|
|
|
* @copyright under GPL 2 licence |
21
|
|
|
*/ |
22
|
|
|
|
23
|
|
|
use RuntimeException; |
24
|
|
|
|
25
|
|
|
class PhpSerial |
26
|
|
|
{ |
27
|
|
|
const OS_UNKNOWN = 0; |
28
|
|
|
const OS_WIN = 1; //WINS32 WINNT Windows |
29
|
|
|
const OS_LINUX = 2; |
30
|
|
|
const OS_CYGWIN = 3; //Cygwin Windows Linux like commands |
31
|
|
|
const OS_UNIX = 4; |
32
|
|
|
const OS_BSD = 5; //FreeBSD or NetBSD or OpenBSD /dev/ttyu1 |
33
|
|
|
const OS_OSX = 6; //Darwin MacOS |
34
|
|
|
const OS_HPUX = 7; //tty1p0 |
35
|
|
|
|
36
|
|
|
const SERIAL_DEVICE_NOTSET = 0; |
37
|
|
|
const SERIAL_DEVICE_SET = 1; |
38
|
|
|
const SERIAL_DEVICE_OPENED = 2; |
39
|
|
|
|
40
|
|
|
const PARITY_NONE = 0; |
41
|
|
|
const PARITY_ODD = 1; |
42
|
|
|
const PARITY_EVEN = 2; |
43
|
|
|
|
44
|
|
|
const FLOW_NONE = 0; //no flow control |
45
|
|
|
const FLOW_RTSCTS = 1; // use RTS/CTS handshaking |
46
|
|
|
const FLOW_XONXOFF = 2; //use XON/XOFF protocol |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Pointer for device |
50
|
|
|
* |
51
|
|
|
* @var resource |
52
|
|
|
*/ |
53
|
|
|
protected $handle = null; |
54
|
|
|
/** |
55
|
|
|
* Data buffer |
56
|
|
|
* |
57
|
|
|
* @var string |
58
|
|
|
*/ |
59
|
|
|
protected $buffer = ""; |
60
|
|
|
/** |
61
|
|
|
* This var says if buffer should be flushed by write (true) or |
62
|
|
|
* manually (false) |
63
|
|
|
* |
64
|
|
|
* @var bool |
65
|
|
|
*/ |
66
|
|
|
protected $autoflush = false; |
67
|
|
|
/** |
68
|
|
|
* Wait time after send data to serial |
69
|
|
|
* |
70
|
|
|
* @var float |
71
|
|
|
*/ |
72
|
|
|
protected $waittime = 0.1; |
73
|
|
|
/** |
74
|
|
|
* OS type where php is running |
75
|
|
|
* linux is default |
76
|
|
|
* |
77
|
|
|
* @var int |
78
|
|
|
*/ |
79
|
|
|
protected $ostype = 2; |
80
|
|
|
/** |
81
|
|
|
* Mode command to set up serial port |
82
|
|
|
* formated device mode for especific OS use |
83
|
|
|
* |
84
|
|
|
* @var string |
85
|
|
|
*/ |
86
|
|
|
protected $mode = ''; |
87
|
|
|
/** |
88
|
|
|
* Status of port |
89
|
|
|
* NoSet, Set or Open |
90
|
|
|
* |
91
|
|
|
* @var int |
92
|
|
|
*/ |
93
|
|
|
protected $state = self::SERIAL_DEVICE_NOTSET; |
94
|
|
|
/** |
95
|
|
|
* Port name |
96
|
|
|
* |
97
|
|
|
* @var string |
98
|
|
|
*/ |
99
|
|
|
protected $port = '/dev/ttyS0'; |
100
|
|
|
/** |
101
|
|
|
* Data bits |
102
|
|
|
* |
103
|
|
|
* @var int |
104
|
|
|
*/ |
105
|
|
|
protected $databits = 8; |
106
|
|
|
/** |
107
|
|
|
* Baud Rate |
108
|
|
|
* |
109
|
|
|
* @var int |
110
|
|
|
*/ |
111
|
|
|
protected $baudrate = 9600; |
112
|
|
|
/** |
113
|
|
|
* Parity |
114
|
|
|
* |
115
|
|
|
* @var int |
116
|
|
|
*/ |
117
|
|
|
protected $parity = self::PARITY_NONE; |
118
|
|
|
/** |
119
|
|
|
* Stop Bits |
120
|
|
|
* |
121
|
|
|
* @var float |
122
|
|
|
*/ |
123
|
|
|
protected $stopbits = 1; |
124
|
|
|
/** |
125
|
|
|
* Flow Control |
126
|
|
|
* |
127
|
|
|
* @var int |
128
|
|
|
*/ |
129
|
|
|
protected $flowcontrol = self::FLOW_NONE; |
130
|
|
|
/** |
131
|
|
|
* Formated device name command |
132
|
|
|
* |
133
|
|
|
* @var string |
134
|
|
|
*/ |
135
|
|
|
protected $device = '/dev/ttyS0'; |
136
|
|
|
/** |
137
|
|
|
* Formated Data Bits command |
138
|
|
|
* |
139
|
|
|
* @var string |
140
|
|
|
*/ |
141
|
|
|
protected $formatedDataBits = 'cs8'; |
142
|
|
|
/** |
143
|
|
|
* Formated Baud Rate command |
144
|
|
|
* |
145
|
|
|
* @var string |
146
|
|
|
*/ |
147
|
|
|
protected $formatedBaudRate = '9600'; |
148
|
|
|
/** |
149
|
|
|
* Formated parity command |
150
|
|
|
* |
151
|
|
|
* @var string |
152
|
|
|
*/ |
153
|
|
|
protected $formatedParity = '-parenb'; |
154
|
|
|
/** |
155
|
|
|
* Formated stop bits command |
156
|
|
|
* |
157
|
|
|
* @var string |
158
|
|
|
*/ |
159
|
|
|
protected $formatedStopBits = '-cstopb'; |
160
|
|
|
/** |
161
|
|
|
* Formated flow control command |
162
|
|
|
* |
163
|
|
|
* @var string |
164
|
|
|
*/ |
165
|
|
|
protected $formatedFlowControl = 'clocal -crtscts -ixon -ixoff'; |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Parity data |
169
|
|
|
* |
170
|
|
|
* @var array |
171
|
|
|
*/ |
172
|
|
|
private $parityargs = [ |
173
|
|
|
"none" => [0, "-parenb"], |
174
|
|
|
"odd" => [1, "parenb parodd"], |
175
|
|
|
"even" => [2, "parenb -parodd"] |
176
|
|
|
]; |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Basud Rate data |
180
|
|
|
* |
181
|
|
|
* @var array |
182
|
|
|
*/ |
183
|
|
|
private $baudsargs = array ( |
184
|
|
|
110 => 11, |
185
|
|
|
150 => 15, |
186
|
|
|
300 => 30, |
187
|
|
|
600 => 60, |
188
|
|
|
1200 => 12, |
189
|
|
|
2400 => 24, |
190
|
|
|
4800 => 48, |
191
|
|
|
9600 => 96, |
192
|
|
|
19200 => 19, |
193
|
|
|
38400 => 38400, |
194
|
|
|
57600 => 57600, |
195
|
|
|
115200 => 115200 |
196
|
|
|
); |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Constructor |
200
|
|
|
* Set ostype parameter |
201
|
|
|
* |
202
|
14 |
|
* @param int $forceOS |
203
|
|
|
*/ |
204
|
14 |
|
public function __construct($forceOS = null) |
205
|
|
|
{ |
206
|
|
|
if (! is_null($forceOS)) { |
207
|
|
|
if ($this->ostype !== $forceOS && ($forceOS > 0 && $forceOS < 8)) { |
208
|
|
|
$this->ostype = $forceOS; |
209
|
|
|
//clear params |
210
|
|
|
$this->clearParams(); |
211
|
14 |
|
} |
212
|
|
|
} else { |
213
|
14 |
|
$this->ostype = $this->getOs(); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Clear class params |
219
|
|
|
* Used for testing proporses |
220
|
|
|
*/ |
221
|
|
|
protected function clearParams() |
222
|
|
|
{ |
223
|
|
|
$this->mode = null; |
224
|
|
|
$this->state = null; |
225
|
|
|
$this->port = null; |
226
|
|
|
$this->databits = null; |
227
|
|
|
$this->baudrate = null; |
228
|
|
|
$this->parity = null; |
229
|
|
|
$this->stopbits = null; |
230
|
|
|
$this->flowcontrol = null; |
231
|
|
|
$this->device = null; |
232
|
|
|
$this->formatedDataBits = null; |
233
|
|
|
$this->formatedBaudRate = null; |
234
|
|
|
$this->formatedParity = null; |
235
|
|
|
$this->formatedStopBits = null; |
236
|
|
|
$this->formatedFlowControl = null; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
14 |
|
* Close port |
241
|
|
|
*/ |
242
|
14 |
|
public function __destruct() |
243
|
14 |
|
{ |
244
|
|
|
$this->close(); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Open set port |
249
|
|
|
* |
250
|
2 |
|
* @return boolean |
251
|
|
|
*/ |
252
|
2 |
|
public function open() |
253
|
|
|
{ |
254
|
|
|
if ($this->state === self::SERIAL_DEVICE_OPENED && is_resource($this->handle)) { |
255
|
|
|
return true; |
256
|
|
|
} |
257
|
2 |
|
$timeout = 10; //seconds |
258
|
2 |
|
for ($i = 0; $i < $timeout; $i++) { |
259
|
2 |
|
$this->handle = @fopen($this->device, 'r+bn'); |
260
|
1 |
|
if ($this->handle) { |
261
|
1 |
|
break; |
262
|
1 |
|
} |
263
|
|
|
sleep(1); |
264
|
1 |
|
} |
265
|
1 |
View Code Duplication |
if ($this->handle === false) { |
|
|
|
|
266
|
1 |
|
$this->handle = null; |
267
|
|
|
$this->state = self::SERIAL_DEVICE_NOTSET; |
268
|
|
|
throw new RuntimeException('Fail to open device. Check permissions.'); |
269
|
|
|
} |
270
|
|
|
stream_set_blocking($this->handle, false); |
271
|
|
|
$this->state = self::SERIAL_DEVICE_OPENED; |
272
|
|
|
return true; |
273
|
|
|
} |
274
|
14 |
|
|
275
|
|
|
/** |
276
|
14 |
|
* Close serial port |
277
|
13 |
|
* |
278
|
|
|
* @return boolean |
279
|
1 |
|
*/ |
280
|
1 |
|
public function close() |
281
|
1 |
|
{ |
282
|
1 |
|
if ($this->state !== self::SERIAL_DEVICE_OPENED || ! is_resource($this->handle)) { |
283
|
|
|
return true; |
284
|
|
|
} |
285
|
|
View Code Duplication |
if (fclose($this->handle)) { |
|
|
|
|
286
|
|
|
$this->handle = null; |
287
|
|
|
$this->state = self::SERIAL_DEVICE_SET; |
288
|
|
|
return true; |
289
|
|
|
} |
290
|
2 |
|
return false; |
291
|
|
|
} |
292
|
2 |
|
|
293
|
|
|
/** |
294
|
|
|
* Returns the setup configuration for serial port |
295
|
2 |
|
* this command will be exectuted in terminal |
296
|
|
|
* |
297
|
|
|
* @return string |
298
|
|
|
*/ |
299
|
2 |
|
public function getSetUp() |
300
|
2 |
|
{ |
301
|
2 |
|
return $this->mode; |
302
|
2 |
|
} |
303
|
2 |
|
|
304
|
2 |
|
/** |
305
|
|
|
* Use class parameters to configure the serial port |
306
|
2 |
|
* before the serial port is opened it must be configured, |
307
|
|
|
* and in windows environment, all sets at a single time |
308
|
2 |
|
* |
309
|
|
|
* @return bool |
310
|
2 |
|
*/ |
311
|
2 |
|
public function setUp() |
312
|
2 |
|
{ |
313
|
2 |
|
if ($this->state === self::SERIAL_DEVICE_SET) { |
314
|
2 |
|
return true; |
315
|
2 |
|
} |
316
|
|
|
if ($this->ostype == 0) { |
317
|
2 |
|
return false; |
318
|
|
|
} |
319
|
|
|
$modesos = [ |
320
|
|
|
1 => 'MODE', //windows mode com4: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off |
321
|
|
|
2 => "stty -F", //linux |
322
|
|
|
3 => "stty -F", //cygwin |
323
|
|
|
4 => 'stty -F', //unix |
324
|
|
|
5 => 'stty -F', //BSD |
325
|
|
|
6 => "stty -f", //MacOS |
326
|
|
|
7 => 'stty -F' //HPUX |
327
|
|
|
]; |
328
|
|
|
$mode = $modesos[$this->ostype] |
329
|
|
|
. " " |
330
|
|
|
. "$this->device " |
331
|
|
|
. "$this->formatedBaudRate " |
332
|
|
|
. "$this->formatedParity " |
333
|
|
|
. "$this->formatedDataBits " |
334
|
|
|
. "$this->formatedStopBits " |
335
|
|
|
. "$this->formatedFlowControl"; |
336
|
|
|
|
337
|
|
|
$out = ''; |
338
|
|
|
if ($this->execCommand($mode, $out) != 0) { |
|
|
|
|
339
|
|
|
throw new RuntimeException("SetUP fail with: ".$out[1]); |
340
|
|
|
} |
341
|
|
|
$this->mode = $mode; |
342
|
|
|
$this->state = self::SERIAL_DEVICE_SET; |
343
|
|
|
return true; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* Set automatic send massage to serial |
348
|
|
|
* |
349
|
|
|
* @param bool $auto |
350
|
|
|
* @param float $waittime |
351
|
|
|
*/ |
352
|
|
|
public function setAuto($auto, $waittime) |
353
|
|
|
{ |
354
|
|
|
if (! is_bool($auto)) { |
355
|
|
|
$data = false; |
|
|
|
|
356
|
|
|
} |
357
|
|
|
if (! is_float($waittime)) { |
358
|
|
|
$waittime = 0.1; |
359
|
|
|
} |
360
|
|
|
$this->waittime = $waittime; |
361
|
|
|
$this->autoflush = $auto; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Returns automatic mode |
366
|
|
|
* |
367
|
|
|
* @return bool |
368
|
|
|
*/ |
369
|
|
|
public function getAuto() |
370
|
|
|
{ |
371
|
|
|
return $this->autoflush; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Read serial port |
376
|
|
|
* |
377
|
|
|
* @param int $count Number of characters to be read (will stop before |
378
|
|
|
* if less characters are in the buffer) |
379
|
|
|
* @return string |
380
|
|
|
*/ |
381
|
|
|
public function read($count = 0) |
382
|
|
|
{ |
383
|
|
|
if ($this->state !== self::SERIAL_DEVICE_OPENED) { |
384
|
|
|
return ''; |
385
|
|
|
} |
386
|
|
|
$content = ""; |
387
|
|
|
$i = 0; |
388
|
|
|
// Windows port reading procedures still buggy |
389
|
|
|
// Behavior in OSX isn't to wait for new data to recover, but just |
390
|
|
|
// grabs what's there! Doesn't always work perfectly for me in OSX |
391
|
|
|
if ($count !== 0) { |
392
|
|
|
do { |
393
|
|
|
if ($i > $count) { |
394
|
|
|
$content .= fread($this->handle, ($count - $i)); |
395
|
|
|
} else { |
396
|
1 |
|
$content .= fread($this->handle, 128); |
397
|
|
|
} |
398
|
|
|
} while (($i += 128) === strlen($content)); |
399
|
1 |
|
return $content; |
400
|
|
|
} |
401
|
1 |
|
do { |
402
|
1 |
|
$content .= fread($this->handle, 128); |
403
|
|
|
} while (($i += 128) === strlen($content)); |
404
|
|
|
return $content; |
405
|
1 |
|
} |
406
|
1 |
|
|
407
|
1 |
|
/** |
408
|
1 |
|
* Write data to buffer or serial port |
409
|
|
|
* depends of getAuto() |
410
|
|
|
* if getAuto() == true this command writes directly to port |
411
|
|
|
* if getAuto() == false this command writes to buffer (default) |
412
|
|
|
* |
413
|
|
|
* @param string $data |
414
|
|
|
* @return boolean |
415
|
1 |
|
*/ |
416
|
1 |
|
public function write($data) |
417
|
1 |
|
{ |
418
|
|
|
$this->buffer .= $data; |
419
|
|
|
if ($this->autoflush === true) { |
420
|
|
|
$this->flush(); |
421
|
|
|
usleep((int) ($this->waittime * 1000000)); |
422
|
|
|
} |
423
|
|
|
return true; |
424
|
1 |
|
} |
425
|
|
|
|
426
|
1 |
|
/** |
427
|
|
|
* Flushs imediatly data to serial port |
428
|
|
|
* |
429
|
|
|
* @return boolean |
430
|
|
|
*/ |
431
|
|
|
public function flush() |
432
|
|
|
{ |
433
|
|
|
if (fwrite($this->handle, $this->buffer) !== false) { |
434
|
1 |
|
$this->buffer = ""; |
435
|
|
|
return true; |
436
|
1 |
|
} |
437
|
|
|
return false; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Set port name |
442
|
|
|
* |
443
|
|
|
* @param string $port |
444
|
|
|
*/ |
445
|
|
|
public function setPort($port) |
446
|
1 |
|
{ |
447
|
|
|
//identify input if $port like COM?? even in others OS |
448
|
1 |
|
$flagWinMode = preg_match("@^COM(\d+):?$@i", $port, $matches); |
449
|
|
|
//select port from OS type |
450
|
|
|
switch ($this->ostype) { |
451
|
1 |
|
case self::OS_WIN: |
452
|
1 |
|
$this->device = ($flagWinMode) ? "COM$matches[1]:" : $port; |
453
|
1 |
|
break; |
454
|
|
|
case self::OS_LINUX: |
455
|
|
|
case self::OS_CYGWIN: |
456
|
|
|
$this->device = ($flagWinMode) ? "/dev/ttyS".($matches[1]-1) : $port; |
457
|
|
|
break; |
458
|
|
|
case self::OS_UNIX: |
459
|
|
|
case self::OS_BSD: |
460
|
|
|
case self::OS_OSX: |
461
|
2 |
|
case self::OS_HPUX: |
462
|
|
|
default: |
463
|
2 |
|
$this->device = $port; |
464
|
|
|
} |
465
|
|
|
$this->port = $port; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* Returns port name |
470
|
|
|
* |
471
|
|
|
* @return string |
472
|
1 |
|
*/ |
473
|
|
|
public function getPort() |
474
|
1 |
|
{ |
475
|
1 |
|
return $this->port; |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
/** |
479
|
1 |
|
* Returns device formated name |
480
|
|
|
* |
481
|
|
|
* @return string |
482
|
|
|
*/ |
483
|
|
|
public function getDevice() |
484
|
|
|
{ |
485
|
|
|
return $this->device; |
486
|
|
|
} |
487
|
|
|
|
488
|
1 |
|
/** |
489
|
|
|
* Sets the length of a character. |
490
|
1 |
|
* length of a character (5 <= length <= 8) |
491
|
|
|
* |
492
|
|
|
* @param int $length |
493
|
1 |
|
* @return boolean |
494
|
1 |
|
*/ |
495
|
1 |
|
public function setDataBits($length) |
496
|
|
|
{ |
497
|
|
|
if ($length < 5 || $length > 8) { |
498
|
|
|
$length = 8; |
499
|
|
|
} |
500
|
|
|
$this->databits = $length; |
501
|
|
|
$this->formatedDataBits = $this->zDataBits($length); |
502
|
|
|
return true; |
503
|
2 |
|
} |
504
|
|
|
|
505
|
2 |
|
/** |
506
|
|
|
* Returns char length |
507
|
|
|
* |
508
|
|
|
* @return int |
509
|
|
|
*/ |
510
|
|
|
public function getDataBits() |
511
|
|
|
{ |
512
|
|
|
return $this->databits; |
513
|
|
|
} |
514
|
1 |
|
|
515
|
|
|
/** |
516
|
1 |
|
* Format data bits commands |
517
|
1 |
|
* |
518
|
|
|
* @param int $length |
519
|
|
|
* @return string |
520
|
|
|
*/ |
521
|
1 |
|
protected function zDataBits($length) |
522
|
|
|
{ |
523
|
|
|
$fdatabits = "cs$length"; |
524
|
|
|
if ($this->ostype == self::OS_WIN) { |
525
|
|
|
//windows |
526
|
|
|
$fdatabits = "DATA=$length"; |
527
|
|
|
} |
528
|
|
|
return $fdatabits; |
529
|
|
|
} |
530
|
|
|
|
531
|
1 |
|
/** |
532
|
|
|
* Set serial baud rate |
533
|
1 |
|
* |
534
|
|
|
* @param int $rate |
535
|
|
|
* @return boolean |
536
|
1 |
|
*/ |
537
|
1 |
|
public function setBaudRate($rate) |
538
|
1 |
|
{ |
539
|
|
|
if (! isset($this->baudsargs[$rate])) { |
540
|
|
|
$rate = 9600; |
541
|
|
|
} |
542
|
|
|
$this->baudrate = $rate; |
543
|
|
|
$this->formatedBaudRate = $this->zBaudRate($rate); |
544
|
|
|
return true; |
545
|
|
|
} |
546
|
2 |
|
|
547
|
|
|
/** |
548
|
2 |
|
* Return baud rate |
549
|
2 |
|
* |
550
|
1 |
|
* @return int |
551
|
1 |
|
*/ |
552
|
1 |
|
public function getBaudRate() |
553
|
|
|
{ |
554
|
|
|
return $this->baudrate; |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
/** |
558
|
|
|
* Format baud rate command |
559
|
|
|
* |
560
|
|
|
* @param int $rate |
561
|
|
|
* @return string |
562
|
|
|
*/ |
563
|
|
|
protected function zBaudRate($rate) |
564
|
1 |
|
{ |
565
|
|
|
$baud = "$rate"; |
566
|
1 |
|
if ($this->ostype == self::OS_WIN) { |
567
|
1 |
|
//windows |
568
|
|
|
$baud = "BAUD=".$this->baudsargs[$rate]; |
569
|
|
|
} |
570
|
|
|
return $baud; |
571
|
1 |
|
} |
572
|
|
|
|
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Sets parity mode |
576
|
|
|
* |
577
|
|
|
* @param string $parity odd, even, none |
578
|
|
|
* @return boolean |
579
|
|
|
*/ |
580
|
|
|
public function setParity($parity) |
581
|
|
|
{ |
582
|
|
|
if (! isset($this->parityargs[$parity])) { |
583
|
|
|
$parity = 'none'; |
584
|
1 |
|
} |
585
|
|
|
$this->parity = $this->parityargs[$parity][0]; |
586
|
1 |
|
$this->formatedParity = $this->zParity($parity); |
587
|
|
|
return true; |
588
|
|
|
} |
589
|
1 |
|
|
590
|
1 |
|
/** |
591
|
1 |
|
* Get parity mode set |
592
|
|
|
* |
593
|
|
|
* @return string |
594
|
|
|
*/ |
595
|
|
|
public function getParity() |
596
|
|
|
{ |
597
|
|
|
switch ($this->parity) { |
598
|
|
|
case 0: |
599
|
2 |
|
return 'none'; |
600
|
|
|
case 1: |
601
|
2 |
|
return 'odd'; |
602
|
|
|
case 2: |
603
|
|
|
return 'even'; |
604
|
|
|
} |
605
|
|
|
} |
606
|
|
|
|
607
|
|
|
/** |
608
|
|
|
* Format parity command |
609
|
|
|
* |
610
|
1 |
|
* @param string $parity |
611
|
|
|
* @return string |
612
|
1 |
|
*/ |
613
|
1 |
|
protected function zParity($parity) |
614
|
|
|
{ |
615
|
|
|
$fparity = $this->parityargs[$parity][1]; |
616
|
1 |
|
if ($this->ostype == self::OS_WIN) { |
617
|
|
|
//windows |
618
|
|
|
$fparity = "PARITY=" . strtoupper(substr($parity, 0, 1)); |
619
|
|
|
} |
620
|
|
|
return $fparity; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
|
624
|
|
|
/** |
625
|
|
|
* Set length of stop bits |
626
|
|
|
* the length of a stop bit. |
627
|
|
|
* It must be either 1, 1.5 or 2. |
628
|
|
|
* 1.5 is not supported under linux and on some computers. |
629
|
1 |
|
* |
630
|
|
|
* @param float $length |
631
|
|
|
* @return boolean |
632
|
1 |
|
*/ |
633
|
|
|
public function setStopBits($length) |
634
|
|
|
{ |
635
|
1 |
|
if ($length !== 1 && $length !== 1.5 && $length !== 2) { |
636
|
1 |
|
$length = 1; |
637
|
1 |
|
} |
638
|
|
|
$this->stopbits = $length; |
|
|
|
|
639
|
|
|
$this->formatedStopBits = $this->zStopBits($length); |
640
|
|
|
return true; |
641
|
1 |
|
} |
642
|
1 |
|
|
643
|
|
|
/** |
644
|
|
|
* Return stop bits set |
645
|
|
|
* |
646
|
|
|
* @return float |
647
|
|
|
*/ |
648
|
|
|
public function getStopBits() |
649
|
|
|
{ |
650
|
2 |
|
return $this->stopbits; |
651
|
|
|
} |
652
|
2 |
|
|
653
|
2 |
|
/** |
654
|
1 |
|
* Format stop bit command |
655
|
1 |
|
* |
656
|
|
|
* @param float $length |
657
|
1 |
|
* @return string |
658
|
1 |
|
*/ |
659
|
|
|
public function zStopBits($length) |
660
|
|
|
{ |
661
|
|
|
$stopb = (($length == 1) ? "-" : "") . "cstopb"; |
662
|
|
|
if ($this->ostype === self::OS_WIN) { |
663
|
|
|
$stopb = "STOP=" . $length; |
664
|
|
|
} |
665
|
|
|
return $stopb; |
666
|
|
|
} |
667
|
|
|
|
668
|
1 |
|
/** |
669
|
|
|
* Set the flow control mode. |
670
|
|
|
* Availible modes : |
671
|
|
|
* "none" : no flow control |
672
|
1 |
|
* "rts/cts" : use RTS/CTS handshaking |
673
|
|
|
* "xon/xoff" : use XON/XOFF protocol |
674
|
1 |
|
* |
675
|
|
|
* @param string $flow |
676
|
1 |
|
* @return boolean |
677
|
|
|
*/ |
678
|
1 |
|
public function setFlowControl($flow) |
679
|
|
|
{ |
680
|
1 |
|
switch ($flow) { |
681
|
|
|
case 'rts/cts': |
682
|
1 |
|
$this->flowcontrol = self::FLOW_RTSCTS; |
683
|
|
|
break; |
684
|
1 |
|
case 'xon/xoff': |
685
|
1 |
|
$this->flowcontrol = self::FLOW_XONXOFF; |
686
|
1 |
|
break; |
687
|
|
|
default: |
688
|
|
|
$this->flowcontrol = self::FLOW_NONE; |
689
|
|
|
} |
690
|
|
|
$this->formatedFlowControl = $this->zFlowControl($this->flowcontrol); |
691
|
|
|
return true; |
692
|
|
|
} |
693
|
|
|
|
694
|
14 |
|
/** |
695
|
|
|
* Returns flow control set |
696
|
14 |
|
* |
697
|
|
|
* @return string |
698
|
14 |
|
*/ |
699
|
|
|
public function getFlowControl() |
700
|
14 |
|
{ |
701
|
|
|
switch ($this->flowcontrol) { |
702
|
14 |
|
case 0: |
703
|
14 |
|
return 'none'; |
704
|
|
|
case 1: |
705
|
|
|
return 'rts/cts'; |
706
|
|
|
case 2: |
707
|
|
|
return 'xon/xoff'; |
708
|
|
|
} |
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
/** |
712
|
|
|
* Return flow control command formated for OP type |
713
|
|
|
* |
714
|
|
|
* @param int $flow |
715
|
|
|
* @return string |
716
|
|
|
*/ |
717
|
|
|
protected function zFlowControl($flow) |
718
|
|
|
{ |
719
|
|
|
$modeos = [ |
720
|
|
|
//windows |
721
|
|
|
self::OS_WIN => [ |
722
|
|
|
"xon=off octs=off rts=on", |
723
|
|
|
"xon=off octs=on rts=hs", |
724
|
|
|
"xon=on octs=off rts=on" |
725
|
|
|
], |
726
|
|
|
//linux |
727
|
|
|
self::OS_LINUX => [ |
728
|
|
|
"clocal -crtscts -ixon -ixoff", |
729
|
|
|
"-clocal crtscts -ixon -ixoff", |
730
|
|
|
"-clocal -crtscts ixon ixoff" |
731
|
|
|
], |
732
|
|
|
//cygwin |
733
|
|
|
self::OS_CYGWIN => [ |
734
|
|
|
"clocal -crtscts -ixon -ixoff", |
735
|
|
|
"-clocal crtscts -ixon -ixoff", |
736
|
|
|
"-clocal -crtscts ixon ixoff" |
737
|
|
|
], |
738
|
|
|
//unix |
739
|
|
|
self::OS_UNIX => [ |
740
|
|
|
"clocal -crtscts -ixon -ixoff", |
741
|
|
|
"-clocal crtscts -ixon -ixoff", |
742
|
|
|
"-clocal -crtscts ixon ixoff" |
743
|
|
|
], |
744
|
|
|
//bsd |
745
|
|
|
self::OS_BSD => [ |
746
|
|
|
"clocal -crtscts -ixon -ixoff", |
747
|
|
|
"-clocal crtscts -ixon -ixoff", |
748
|
|
|
"-clocal -crtscts ixon ixoff" |
749
|
|
|
], |
750
|
|
|
//macos |
751
|
|
|
self::OS_OSX => [ |
752
|
|
|
"clocal -crtscts -ixon -ixoff", |
753
|
|
|
"-clocal crtscts -ixon -ixoff", |
754
|
|
|
"-clocal -crtscts ixon ixoff" |
755
|
|
|
], |
756
|
|
|
//hpux |
757
|
|
|
self::OS_HPUX => [ |
758
|
|
|
"clocal -crtscts -ixon -ixoff", |
759
|
|
|
"-clocal crtscts -ixon -ixoff", |
760
|
|
|
"-clocal -crtscts ixon ixoff" |
761
|
|
|
] |
762
|
|
|
]; |
763
|
|
|
return (string) $modeos[$this->ostype][$flow]; |
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
/** |
767
|
|
|
* Find OS type |
768
|
|
|
* |
769
|
|
|
* @return int |
770
|
|
|
*/ |
771
|
|
|
protected function getOs() |
772
|
|
|
{ |
773
|
|
|
$oss = strtoupper(substr(PHP_OS, 0, 3)); |
774
|
|
|
switch ($oss) { |
775
|
|
|
case 'DAR': |
776
|
|
|
return self::OS_OSX; |
777
|
|
|
case 'WIN': |
778
|
|
|
return self::OS_WIN; |
779
|
|
|
case 'LIN': |
780
|
|
|
return self::OS_LINUX; |
781
|
|
|
case 'CYG': |
782
|
|
|
return self::OS_CYGWIN; |
783
|
|
|
case 'HPU': |
784
|
|
|
return self::OS_HPUX; |
785
|
|
|
case 'BSD': |
786
|
|
|
return self::OS_BSD; //este esta incorreto |
787
|
|
|
case 'UNI': |
788
|
|
|
return self::OS_UNIX; |
789
|
|
|
default: |
790
|
|
|
return self::OS_UNKNOWN; |
791
|
|
|
} |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
/** |
795
|
|
|
* Exec command line in OS console |
796
|
|
|
* |
797
|
|
|
* @param string $cmd comand line to execute |
798
|
|
|
* @param array $out retorn of this command in terminal |
799
|
|
|
* @return int |
800
|
|
|
*/ |
801
|
|
|
public function execCommand($cmd, &$out = null) |
802
|
|
|
{ |
803
|
|
|
$desc = array( |
804
|
|
|
1 => array("pipe", "w"), |
805
|
|
|
2 => array("pipe", "w") |
806
|
|
|
); |
807
|
|
|
$proc = proc_open($cmd, $desc, $pipes); |
808
|
|
|
$ret = stream_get_contents($pipes[1]); |
809
|
|
|
$err = stream_get_contents($pipes[2]); |
810
|
|
|
fclose($pipes[1]); |
811
|
|
|
fclose($pipes[2]); |
812
|
|
|
$retVal = proc_close($proc); |
813
|
|
|
if (func_num_args() == 2) { |
814
|
|
|
$out = array($ret, $err); |
815
|
|
|
} |
816
|
|
|
return $retVal; |
817
|
|
|
} |
818
|
|
|
} |
819
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.