Linux за българи: Форуми

Програмиране => Web development => Темата е започната от: a_panov в Sep 08, 2007, 12:46



Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: a_panov в Sep 08, 2007, 12:46
Здравейте

Имам проблем да накарам РНР-то да чете и пише в серийния порт под Линукс.
Какво имам и какво съм направил досега:
Тестова установка 1 - Сървър:
Сървъра е с DSL Linux, 2.4 ядро, XAMPP с като РНР има "--enable-dio", в php.ini e зададено да всички грешки и предупреждения. Имам закачен луупбак на серийния порт. /dev/ttyS0 e с права 666 или rw- rw- rw-. Когато подам:
echo "12345" > /dev/ttyS0
командата:
cat /proc/tty/drivers/serial
ми казва че tx се е увеличило с 5 символа и rx също се е увеличило със 5 символа.

Когато стартирам РНР кода за комуникация, нищо не се получава като резултат и не дава никакви грешки и предупреждения. Просто браузъра върти си там и чака, и нищо не става. Пускам командата:
cat /proc/tty/drivers/serial
ми казва че tx  и rx не са се променили.

Тестова установка 1 - Лаптоп:
Сървъра е с Decian Linux, 2.6 ядро, XAMPP (прекопиран от горния сървър) с като РНР има "--enable-dio", в php.ini e зададено да всички грешки и предупреждения. Имам закачен луупбак на серийния порт. /dev/ttyS0 e с права 666 или rw- rw- rw-.  Когато подам:
echo "12345" > /dev/ttyS0
командата:
cat /proc/tty/drivers/serial
ми казва че tx  и rx не се променят, и имат стойности 0.

Когато стартирам РНР кода за комуникация, и подам стринга "12" (два служебни символа се предават) се получава:
Writing ...
4 bytes written.
Try to read ...Read miss...
Read miss...
Read miss...
Read miss...
Read miss...
Read miss...
не може да чете, но!!! Но пак при подаването на командата:
cat /proc/tty/drivers/serial
ми казва че tx  и rx не се променят, и имат стойности 0.

Искам да напиша чиста РНР комуникация със серийния порт използвайки dio. Нужна ми е за софтуер за наблюдение на телефонни централи, за управление на микроконтролери и UPS-и. Искам да стане на РНР защото, критичната маса от потребители на този език вече е прехвърлена и ще е в полза на много хора. При търсенето ми в интернет не попаднах на работещ код.

По този софтуер работят за момента:
Алекс Панов - координатор
Росен Захариев - РНР програмист
Николай - Линукс администрация
Сайт на където ще е изложен кода:
http://www.karatebulgaria.com/alex/

Примерен код

<?php

if(!empty($_POST['command_text']))
{
 $dio_file_name = "/dev/ttyS0";
 
 $dio_file_desc = dio_open($dio_file_name, O_RDWR);//O_CREAT | O_APPEND, O_WRONLY);
 dio_tcsetattr($dio_file_desc, array("baud" => 9600, "bits" => 7, "stop" => 2, "parity" => 2));
 
 $text = $_POST['command_text']."*".chr(13);
 $write_num = dio_write($dio_file_desc, $text);
 echo "Writing ...<br>";echo "".$write_num." bytes written.<br>";
 dio_close($dio_file_desc);
sleep(1);
 echo "Try to read ...";
 
 $dio_file_desc = dio_open($dio_file_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
 # $dio_file_desc = dio_open($dio_file_name, O_NONBLOCK, O_RDONLY);
 dio_tcsetattr($dio_file_desc, array("baud" => 9600, "bits" => 7, "stop" => 2, "parity" => 2));
 
 $read_miss_counter = 0;
 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>";
 #   sleep(1);
   }
  }
  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
}
?>


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 13:07
Интересна задача и все пак аз като човек , който също е писал и пише програми за управление на микроконтролери и у-ва по сериен порт , се питам колко е сигурно
(според Вас) да е на script език , при положение и то точно php , достъпно през уеб :?

засега аз с php през уеб съм се ограничил само за визуализиране и то чрез imagemagic< т.е php ми служи да генерирам картините , който ми трябват за да визуализирам и токлова. Но се мисли в тази насока и за управление, та ;)
ясно е че ще се минава през процес на удостверяване ssl/https или друго, но все пак ;) :-)

А иначе ще погледна скрипта и ще му отделя време :-) Интересна задачка и за 1-ви път виждам Php да позлва serial port , макар че не съм се сънявал , че ще го може :)



EDIT:

АЕ ДА не съм врачка, ама май знам какъв е проблема , линиите за buffer control ... или оп -точно DTS, RTS и прочие

:) Не виждам да сте казали дА НЕ СЕ ПОЛЗВАТ, а ако се ползват не виждам да ги управлявате ;-) :-P :)

А те по подразбиране , начало са включение/ се ползват :-)





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 13:40
"...
echo "12345" > /dev/ttyS0
командата:
cat /proc/tty/drivers/serial
ми казва че tx се е увеличило с 5 символа и rx също се е увеличило със 5 символа.
..."

Това под root ли го пускаш? Пробва ли да го пуснеш по потребителя на Apache-то в конзола да видиш какво става?

И още нещо - няма "санитизация" на POST елементите.


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: a_panov в Sep 08, 2007, 13:43
В Апача се задава от кои IP-та да се достъпва. Софтуера е за Lan не е за web. От УЕБ ще е достърна машината само под SSH за да може да се оправя евентуален бъркоч. На по-късен период ще се ползва ssl/https. Софтуера е само РНР без JavaScript и AJAX. Има валидизация на всички входящи данни. Логване на "всички" потребителски действия, базата данни ще расте най-много от тука. ЛОгване на всички грешки и предупреждения от Мускула и РНР-то, Апача си тъпче два собствени лога за достъпването му и за грешки.

Интерфейса трябва да е стриктен HTML или XHTML

Интерфейса ще е достъпен от модифицирани K-Meleon или Mozilla без статус бар, без тулл барове и файл бар. И по-подразбиране ще се дава да се зарежда страница от сървъра. На сървъра може да се каже да приема конекции само ако браузера се определя като K-Meleon ...

Има много да се доизкусурява.

Но тази комуникация ни закла като агнета по Великден...

Ще съм благодарен ако помогнеш.


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 13:49
Цитат (the_real_maniac @ Сеп. 08 2007,14:07)
EDIT:

АЕ ДА не съм врачка, ама май знам какъв е проблема , линиите за buffer control ... или оп -точно DTS, RTS и прочие

:) Не виждам да сте казали дА НЕ СЕ ПОЛЗВАТ, а ако се ползват не виждам да ги управлявате ;-) :-P :)

А те по подразбиране , начало са включение/ се ползват :-)

А това ? :)

Досега теглих кабелите, че бях разпуснал тестовата остановка последните седмици :) А и пречат като работиш повече по софтуер(а).

едит: та в момента съм вързал само 3->2 (TX1 ->RX2), 2 <- 3 (RX1 <- TX2) и 5 <-> 5  (GND - GND) , без контролни линии, и без тях ще работя за начало :) Но ако ползвате plc-та или някакви маркови /сименс контролери 99% ще ви трябват :)





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: a_panov в Sep 08, 2007, 13:50
"...
echo "12345" > /dev/ttyS0
командата:
cat /proc/tty/drivers/serial
ми казва че tx се е увеличило с 5 символа и rx също се е увеличило със 5 символа.
..."

Това под root ли го пускаш? Пробва ли да го пуснеш по потребителя на Apache-то в конзола да видиш какво става?
---
Ууффф ако искаш да ти дам Име и Парола за сървъра да видиш кое как е. На практика сега мисля че root пуска Апача и echo и cat също ги изпълнява root.

И още нещо - няма "санитизация" на POST елементите.
---
Ако искаш може да проведем един разговор за да ми изясниш донякъде " "санитизация на POST елементите".НА мене тази материя не ми е позната, а може да стигнем до някакво позитивно развитие на нещата.


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 13:57
Само "родителния" процес на Apache се пуска под root, процесите които реално обслужват заявките се пускат под потребителя на Apache ... примерно www-data или nobody.

Аз управлявам паралелния порт през уеб интерфейс и го правя чрез "sudo" - т.е. с root права - предполагам, че и при теб трябва да е така.

A за санитизиацията - имах предвид да "изчистиш" нежеланите символи от $_POST['command_text'] преди да го използваш.


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 14:04
даваш право на Nobody да ползва sudo :? грубо казано ?

Ако си в chroot - ок, но иначе :?

едит: а ти посредством php И dio  ли също осъществяваш комуникацията :?





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 14:10
Е, нали за това е sudo ...


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: a_panov в Sep 08, 2007, 14:15
Само "родителния" процес на Apache се пуска под root, процесите които реално обслужват заявките се пускат под потребителя на Apache ... примерно www-data или nobody.

Аз управлявам паралелния порт през уеб интерфейс и го правя чрез "sudo" - т.е. с root права - предполагам, че и при теб трябва да е така.
---

Да обаче аз имам 666 на /dev/ttyS0 тоест всеки може да го ползва. Ще пробвам от конзолата

A за санитизиацията - имах предвид да "изчистиш" нежеланите символи от $_POST['command_text'] преди да го използваш.
---
това е тест за да  разберем дали работи, нас ни трябва да тръгне после ще се заемем с проверките.


ЗА мене е важно както вие засегнахте да изчистим двете страни: сървърния софтуер и кода за управление


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 14:18
Е да де, но идеята да ползваш Nobody ,  а не root нали е да няма admin Привилегий и възможности, а ако излезе дупка в apache и посредством него се влезе ще влезе като (най-вероятно) като потребителят под който работи apache  и този потребител хоп има SUDO , е браво ? и за какво цялата гимнастика :) вярно прав си:

ами ако ми трябват , както в случея явно, и питам ок sudo , а в  'клетка ли е'/"затвор" ли е :)

питам защото ме вълнува :)


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 14:25
Цитат (the_real_maniac @ Сеп. 08 2007,14:04)
едит: а ти посредством php И dio  ли също осъществяваш комуникацията :?

Не, точно - PHP, но с компилиран файл, като онзи от статията за watchdog-a


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 14:28
Цитат (the_real_maniac @ Сеп. 08 2007,14:18)
Е да де, но идеята да ползваш Nobody ,  а не root нали е да няма admin Привилегий и възможности, а ако излезе дупка в apache и посредством него се влезе ще влезе като (най-вероятно) като потребителят под който работи apache  и този потребител хоп има SUDO , е браво ? и за какво цялата гимнастика :) вярно прав си:

ами ако ми трябват , както в случея явно, и питам ок sudo , а в  'клетка ли е'/"затвор" ли е :)

питам защото ме вълнува :)

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

с chroot на Apache не съм се занимавал :)





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 14:28
Мда на мен това ми е идеята да ползвам отделна програма за комуникацията, която да върши работата и тя да се стартира, нещо от сорта
един tool , който да си върши работата и друг който да го ползва и да си върши своята :)

но ще видим

благодаря за инфото.

едит: @SUDO: да има възможнист за ограничаване и то доста ;) :) и все пак sudo, setuid извън chroot за отдалечен достъп аз много тудно се съгласявам :)



edit: трябва да обновя PHP-то си е че е 4-та версия, но не е 4.2.0 или от коя версия има подръжка за dio не знам.

но факта е че го нямам на моя сървър.

а излизам , довечера обаче ще се тества и все пак за 3-ти път
погледнете си stty -F /dev/ttyS0 -a ! след вашият fopen ;) !
за да видите как го отваряте :)
защото ако има контролни линии, и те не са пресукани кактоп пин 2 с 3  ;-)

аз не виждам вие да сетвате флагове за изкл. на контролни линии и последно , А те по подразбиране са вкл.

успех ! :) :p :)



edit:

даже
можете да викнете следното

system("stty 57600 cread clocal echo -crtscts cs8 -parenb -parodd -ixon ixoff -F /dev/ttyS0");


след това след този ред


   dio_tcsetattr($dio_file_desc, array("baud" => 9600, "bits" => 7, "stop" => 2, "parity" => 2));

system("stty -F /dev/ttyS0 -a"); // ще  е полезно

/* трябва cstopb да е сетнато без - , и parenb да е без или това е odd, едно от двете трябва д е без - , също така трябва да е cs7 , а не cs8 , -crstcts отменя контролните линии , а ixon другите софт. мех. за flow контрол*/



edit: малко ме еяд че не мога дапробвам сега нещата, но не мога да дам от раз ъпдейт на php-то на сървъра  :-)
довечера, айде чао засега.

пп: the.real.maniac@jabber.com



edit: хмм версията ми е по-голяма от 4.2 , но dio функциите ги нямам така илииначе  , странно, мм ще го гледам после.





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: VladSun в Sep 08, 2007, 23:21
@the_real_maniac
Цитат (a_panov @ Сеп. 08 2007,12:46)
... като РНР има "--enable-dio" ...






Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 08, 2007, 23:23
предположих аз , че става дума за конфигурацията , благодаря ;)

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

после a_panov като си направи тестовете ще пише :)

edit:

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

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






Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 09, 2007, 04:08
Примерен код


<?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 си , щото в природата енергия не се губи  :D

маке му ...  :D  :D

изкрейзах , сори :p :)  B)  :)  :)


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: a_panov в Sep 09, 2007, 11:02
Очите са ми на понички. Легнали сме си с 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 в Sep 09, 2007, 11:05
Примерен код
<?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 в Sep 09, 2007, 20:51
е да променливата държаща файловият дексриптор :)
в бързината, но да ;-)

едит:

ок грешка , 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 режима, защото те правилн оразчитат на конф. на порта :)

та

кода

Примерен код

<?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
}
?>







Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 10, 2007, 13:59
Вариант 2, която осигурява noLF / no icanon + 1:1 пращане на данните (да ви кажа raw  е по-хубав варинат).

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

след това 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
}
?>


Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 10, 2007, 16:41
Какво всъщносто прави 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 ;) :)

НО (!;)

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

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

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

и сте готови to go :)

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

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

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

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





Титла: проблем с РНР-то да чете и пише в серийния порт
Публикувано от: the_real_maniac в Sep 13, 2007, 14:05
Първоначлният , оригинален скрипт (даден от A.Panov) има две логически грешки  , заради които не е работил  :)

първата , не пълно указване на х-ките на 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, за малко да забравя :) :-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
}
?>



и така ;)

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

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

;-) :-)