Автор Тема: проблем с РНР-то да чете и пише в серийния порт  (Прочетена 4525 пъти)

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
предположих аз , че става дума за конфигурацията , благодаря '<img'>

проблема е според мен решен , контролнтие линиии не бяха забранени , а не са loopback_нати и се чакат там разрешения (1/0) и т.н, та ... така '<img'>

после a_panov като си направи тестовете ще пише '<img'>

edit:

освен този проблем се оказа че и един МОЖЕ БИ МЪРЗЕЛИВн PHP Програмист поЛУ И***Т  с извинение ... НЕ СИ Е ПОПЪЛНИЛ ИНФОРМАЦИЯТА ДА КАЖЕ че dio_write и dio_read работят в каноничен режим та добре че един 'чужденстранен' колега го е драснал на Php.net в коментар че работи така.

таааа браво PHP.net < браво за подръжката железните сте, благодаря за 2-та часа за дето сте мързели ! благодаря ... и php нема такъв език




Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
Примерен код


<?php
if(!empty($_POST['command_text']))
{

     $dio_file_name = "/dev/ttyS0";

/* така или иначе щем не щем ще работим в каноничен режим */
     exec("stty 9600 parenb -parodd cs7 cstopb cread clocal -crtscts -ixon -ixoff -echo icanon -F /dev/ttyS0");

     $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
     dio_fcntl($dio_file_desc, F_SETFL, 0);

     $text = $_POST['command_text']."*".chr(13);
     $write_num = dio_write($dio_file_desc, $text);
     echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";

     echo "Try to read ...<br>";

     $dio_read1 = dio_read($dio_file_desc, 256);
     echo "Read: ".$dio_read1;

     dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Enter Command: <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>




Ако работите с външно у-во и не искате каноничен режим, но трябва LF за dio_Read че да се върне от извикването си и да даде каквото е прочел дотук и реално пратеното:

Примерен код



<?php
if(!empty($_POST['command_text']))
{

     $dio_file_name = "/dev/ttyS0";

     exec("stty 9600 parenb -parodd cs7 cstopb cread clocal -crtscts -ixon -ixoff -echo raw -F /dev/ttyS0");

     $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
     dio_fcntl($dio_file_desc, F_SETFL, 0);

     echo "Try to read ...<br>";

/* пращаме LF че да се върне dio_read */
     dio_write($fd,"\x41",1);
     $dio_read1 = dio_read($dio_file_desc, 256);
     echo "Read: ".$dio_read1;

     dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Enter Command: <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>




Ако имаше възможност да избираш spec. char за край или да кажеш да го няма поне , демек мин 2 вариант щях да кажа, браво php програмисти правили dio функц, обаче сега мога да кажа .. по-голема простотия ... скоро не бях виждла, но знаех че php е колкто добър толквоа и боза .. жалко

има даже "" -> което не е \0 , мили боже, колко мъка има по света, но нищо компромиси трябват, но и документация трябва, ама тоя мързел не убива
а мъчи

днес мъчи мен и А.Панов , утре ... ще се върне при creator-a си , щото в природата енергия не се губи  '<img'>

маке му ...  '<img'>  '<img'>

изкрейзах , сори ':p' '<img'>  'B)'  '<img'>  '<img'>
Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

a_panov

  • Напреднали
  • *****
  • Публикации: 62
    • Профил
Очите са ми на понички. Легнали сме си с the_real_maniac днес в 5 сутринта. Сега ни бърка тоя LF който се предава в края на комуникацията. DIO-то се намира на тоя адрес:
http://pecl.php.net/package/dio

а самите функции в dio.c са:
Примерен код
/* {{{ proto string dio_read(resource fd[, int n])
   Read n bytes from fd and return them, if n is not specified, read 1k */
PHP_FUNCTION(dio_read)
{
   zval     *r_fd;
   php_fd_t *f;
   char     *data;
   long      bytes = 1024;
   ssize_t   res;

   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &r_fd, &bytes) == FAILURE) {
      return;
   }
   ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);

   if (bytes <= 0) {
      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0.");
      RETURN_FALSE;
   }

   data = emalloc(bytes + 1);
   res = read(f->fd, data, bytes);
   if (res <= 0) {
      efree(data);
      RETURN_NULL();
   }

   data = erealloc(data, res + 1);
   data[res] = 0;

   RETURN_STRINGL(data, res, 0);
}

и другата:
Примерен код
/* {{{ proto int dio_write(resource fd, string data[, int len])
   Write data to fd with optional truncation at length */
PHP_FUNCTION(dio_write)
{
   zval     *r_fd;
   php_fd_t *f;
   char     *data;
   int       data_len;
   long      trunc_len = 0;
   ssize_t   res;

   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &r_fd, &data, &data_len, &trunc_len) == FAILURE) {
      return;
   }

   if (trunc_len < 0 || trunc_len > data_len) {
      php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater or equal to zero and less then the length of the specified string.");
      RETURN_FALSE;
    }

   ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);

   res = write(f->fd, data, trunc_len ? trunc_len : data_len);
   if (res == -1) {
      php_error(E_WARNING, "%s(): cannot write data to file descriptor %d, %s",
              get_active_function_name(TSRMLS_C), f->fd, strerror(errno));
   }

   RETURN_LONG(res);
}

Ако някой може да каже как да премахнем LF, да сподели.
Активен

a_panov

  • Напреднали
  • *****
  • Публикации: 62
    • Профил
Примерен код
<?php
if(!empty($_POST['command_text']))
{

    $dio_file_name = "/dev/ttyS0";

    exec("stty 9600 parenb -parodd cs7 cstopb cread clocal -crtscts -ixon -ixoff -echo raw -F /dev/ttyS0");

    $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
    dio_fcntl($dio_file_desc, F_SETFL, 0);

    $text = $_POST['command_text']."*".chr(13);
    $write_num = dio_write($dio_file_desc, $text);
    echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";

    echo "Try to read ...<br>";

/* пращаме LF че да се върне dio_read */
    dio_write($dio_file_desc,"\x41",1);
    $dio_read1 = dio_read($dio_file_desc, 256);
    echo "Read: ".$dio_read1;

    dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Enter Command: <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>

На първо четене втория код на the_real_maniac трябва да не работи. По-горе съм постнал работещия код. Трябва този ред:
dio_write($fd,"\x41",1);
в кода на the_real_maniac
да се замени с:
dio_write($dio_file_desc,"\x41",1);
както съм направил тука.



Активен

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
е да променливата държаща файловият дексриптор '<img'>
в бързината, но да ;-)

едит:

ок грешка , zend_parse_args 100% не , а при fetch-a

има някакъв resourse destrouctor или е той, но не той прави free memory  , или самият fetch иска LF :? което едва ли .

значи преди това се указва тоя LF и се указва в момента , в който се вика dio-то , няма как иначе да е . не е нито parse args, нито fetch-a.

сега ще гледам кода


едит: значи хванах го

в dio_read , dio_write не прави нищо  по LF  , поне това ми хареса изнесено е от dio_tcsetattr, той сетва канон режим

въпроса е че или dio_open , или dio_fcntl го вика и сетва canon режим, а реда stty е преди това и затова не сработва ок, пък и ние като видяхме че не може без icanon , та raw не стоеше , ае извода

след dio_open & dio_fcntl и dio_tcsetattr (ако ползвате, макар че същото прави и stty) пускате един stty да махне icanon режима, защото те правилн оразчитат на конф. на порта '<img'>

та

кода

Примерен код

<?php
if(!empty($_POST['command_text']))
{

     $dio_file_name = "/dev/ttyS0";

     $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
     dio_fcntl($dio_file_desc, F_SETFL, 0);
/* изчакваме dio-то да си прави номерата и си сетваме каквот ни трябва, като raw сетва и ixon и ixoff на минус, но нарочно за прегледност ги слагам /оставям  */
     exec("stty 9600 parenb -parodd cs7 cstopb cread clocal -crtscts -ixon -ixoff -echo raw -F /dev/ttyS0");

     $text = $_POST['command_text']."*".chr(13)."\x41";
     $write_num = dio_write($dio_file_desc, $text);
     echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";

     echo "Try to read ...<br>";

     $dio_read1 = dio_read($dio_file_desc, 256);
     echo "Read: ".$dio_read1;

     dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Enter Command: <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>





Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
Вариант 2, която осигурява noLF / no icanon + 1:1 пращане на данните (да ви кажа raw  е по-хубав варинат).

т.е ако напишете test ще получите testA (скрипта добавя LF нарочно за да се види че не се имплентира/пипа/процессва от порта), скрипта казва изпратих 5 байта , очевидно е получил и 5 щом тестА '<img'>

след това cat /proc/tty/driver/serial

казва точно +5 , +5 разлика и в tx , и rx  

Важно, тук не се прави настройка на скорост, брой дата битове, стоп, старт и прочие , parity, само маха LF и го прави rx/tx 1:1, нарочно за да е прегледно

за тестове просто слагате връзка м/у 2 и 3 крак/пин на серийният порт за loopback, 5-ти крак няма какво да го пипамета така или иначе порта е един , масата е обща ;-) :-)

Примерен код

<?php
if(!empty($_POST['command_text']))
{

    $dio_file_name = "/dev/ttyS0";

    $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
    dio_fcntl($dio_file_desc, F_SETFL, 0);

    exec("stty -crtscts -ixon -ixoff -echo -icanon -F /dev/ttyS0");

    $text = $_POST['command_text']."\x41";
    $write_num = dio_write($dio_file_desc, $text);
    echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";

    echo "Try to read ...<br>";

    $dio_read1 = dio_read($dio_file_desc, 256);
    echo "Read: ".$dio_read1;

    dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Enter Command: <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>
Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
Какво всъщносто прави dio от версия 1.16 насам :

dio_tcsetattr set-ва по подразбиране

crtscts =  ДА и ICANON = НЕ !

Примерен код

 newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD; /* пуска се CRTSCTS както виждаме а и също така освен Databits, Stopbits, paritybit се позволява recieve-а и "modem" control в/у порта , всичко точно*/
        newtio.c_iflag = IGNPAR; /*игнорирай байтове с парити еррор */
        newtio.c_oflag = 0;
        newtio.c_lflag = 0;       /* ако вместо =0 е ICANON; щяхме да имаме каноничен режим ! */
        newtio.c_cc[VMIN]=1;
        newtio.c_cc[VTIME]=0;
        tcflush(f->fd, TCIFLUSH);
        tcsetattr(f->fd,TCSANOW,&newtio);





т.е какво става , когато dio_open  отвори порта го отваря с подразбиращи се termios -> настройки , който са crtscts on и icanon on, а АКО пуснете dio_tcsetattr  ще махне icanon режима :-)

та затова се изисква LF и т.н защото dio_open отваря порта и по подразбиране той приема default_termios койт ое с icanon = on '<img'> '<img'>

НО (!'<img'>

ако пуснете tcsetattr не би трябвало да сте в ICANON режим :-)

само ви трябва един ред

exec(stty -crtscts -F /dev/ttySx);

и сте готови to go '<img'>

Така че цялата гимнастика горе с  stty не е че лоша, но може да се ползва dio_tcsetattr, знам ли уж за прегледност '<img'>

няма значение.

Това е. Защо всичко продължи толквоа до тук, защото при г-н Панов на машината имаше проблем при tx/rx броя байтове , несъответствие , в крайна сметка се оказа, че проблема не е вphp скрипта, не е в dio, не е в stty , ами в самата машина и/или дистро, той ще си разбере какво точно.

Но аз пък задълбах и изкарах тея неща и тествах на мойта машина :-)



Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

the_real_maniac

  • Напреднали
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
Първоначлният , оригинален скрипт (даден от A.Panov) има две логически грешки  , заради които не е работил  '<img'>

първата , не пълно указване на х-ките на fd -или файла -> т.е че е сериен порт, опции като O_ASYNC и т.н, това се прави с dio_fcntl , ако не искате да ползвате fopen примерно за това / в слукчея dio_open, но не са му дали тези възможности, затова има dio_fcntl , докато ако беше C програмиране

и man 2 open и man fcntl ще ви покажат, че можете и от двете места да сетнете нужните флагове , но ... в слукче не е така, та специфики и ето грешка номер 1

1. изпуснат fcntl set -> dio_fcntl($fd, F_SETFL, 0)
в случея $fd има друго име, но това е ясно

грешка номер 2

fopen -  самият dio_open т.е не подава необходимите параметри към пак fd, пак да се работи правилно с този файл/ув-о, защото той е сериен порт.

оо и грешка номер 3, за малко да забравя '<img'> :-P , хихи , сега мие паднало, мноогоо малко space & enter слагани , направо е мъчение, моля те слагай(Те) повече форматиране в кода
--

edit: нещо code не можа да запази форматирането и tab-овете .. пфу , е сори , не зависи от мене.

ето кода

Примерен код



<?php

if(!empty($_POST['command_text']))
{

   $dio_file_name = "/dev/ttyS0";

   /* тук имаше грешка ... или по-точно неточност, която сигурно е  пречела */
   $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NDELAY | O_NOCTTY);
        dio_fcntl($dio_file_desc, F_SETFL, 0);
   dio_tcsetattr($dio_file_desc, array("baud" => 9600, "bits" => 7, "stop" => 2, "parity" => 2));

   /* този ред нарочно, ако го ползвате за force на натройките; е след tcsetattr, защото той променя настройките
    - махаме контролнтие линии
    - махаме софтуерният flow control
    - махаме echo , не ни трябва
   другото tcsetattr добре е сетнал или оставил по defautl, който ни устройва
   */
 */
/*   exec("stty -crtscts--ixon -ixoff -echo -F /dev/ttyS0");     */

/* chr(65) = 'A' или  LF, демонтрираме , че не се имплентира
+ (chr13) = '\n' (enter), който е символа за служебен край , който по долу
цикълт чакак и така */
   $text = $_POST['command_text']."*".chr(65).chr(13);
   $write_num = dio_write($dio_file_desc, $text);
   echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";

   echo "Try to read ...<br>";

/*debug if needed*/
   exec("stty -F /dev/ttyS0 -a > /tmp/o");


   /* като цяло този while не мисля че така трябва да бъде или въобще
   дали да е в тази форма , проверката , но това е ясно ще има някаквъ timeout
        */
   $read_miss_counter = 0;

/*
test
   $dio_read1 = dio_read($dio_file_desc,256);
   echo "Read \"".$dio_read1."\"<br>";
*/

/* ВАЖНО , цикълт спира до ЕНТЪР и не го изписва, т.е при 5 байта общо ще виите 4, защото 5-тият
винаги е ентър и той не се показва, той е (служебен) край;) :) */
   while(($dio_read = dio_read($dio_file_desc, 1)) != chr(13))
   {
    if($dio_read == "")
    {
     $read_miss_counter++;
     if($read_miss_counter == 20)
     {
      break;
     }
     else
     {
      echo "Read miss...<br>";
   
     }
    }
    else
    {
     echo "Read \"".$dio_read."\"<br>";
    }
   }
   
   dio_close($dio_file_desc);

}
else
{
?>

<form method = "post">
Въведете команда(без терминиращите символи): <input type = 'text' name = 'command_text' maxlength= '131' value = "">
<input type = "submit" name = "submit_button" value = "Go!">
</form>
<?php
}
?>



и така '<img'>

Задачката е приключена и най-вече довършена, аз съм доволен, че нещата се изясниха и проработиха - работят на 6, ясно, точно и правилно '<img'>

пп: и все пак php, колкото и добър, толквоа и лигав език ... преди все го казвах без да съм 100% убеден, е вече съм '<img'> за хубаво и лошо, езикът обаче е много гъвкав.

;-) :-)
Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)