День добрый, есть система которая должна получать команды в байтовом формате по ethernet и при необходимости в байтовом же формате передавать какой-то ответ, опять же по ethernet.
В качестве базового котнроллера Arduino UNO, в качестве ethernet shield контроллерна базе ENC28j60.
Если делать на W5100, то там поставленная задача решается просто, например вот так
EthernetClient client = server.available();
if (client.available()>0)
{
serial_data=client.read();
if (serial_data==3)
server.write('1');
Но на руках есть именно ENC28j60. Так что комментарии типа забей и возьми W5100 не конструктивны
Для чипа ENC28j60 использовал разные библиотеки в итоге заработала только EherCard, взятая с github, причем старая версия от 2014 года. С остальными библиотеками столкнусля с ошибками на стадии компиляции примеров (среда arduino ide 1.6.5 с оф сайта) причина их не понятна, но не в этом суть.
От сетей я довольно далек поэтому после нескольких дней копания библиотеки и чтения форумов не смог ничего придумать на замену примера выше.
Почти все примеры имеют отношение к общению через веб. У меня задача другая, открываю какой-либо порт и из приложения кидаю команды, представляющие собой числа в hex объемом 1 байт, arduino их принимает, что-то делает и если надо отвечает через этот же порт в приложение каким-то числом в такой же форме.
Смотрел видео Осипова
https://www.youtube....h?v=PPB2Xvubt4s
https://www.youtube....h?v=RgJnYsTmM5A
но то что нужно я там не нашел
Я хочу забирать из ТСР пакета байт 0х0036, выделен черным.
Как мне казалось можно использовать конструкции как у Осипова типа
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if (pos){
Serial.println(pos);
bfill = ether.tcpOffset();
char *data = (char *) Ethernet::buffer + pos;
if (strncmp("T", data, 1) != 0) { //сравниваем первый значащий символ в полученном пакете
Serial.println('1');
}
else {Serial.println('2');}
}
Serial здесь для отладки стоят. В результате в мониторе пусто. то есть даже нет захода в первое условие.
Погонял через Wireshark скетч Осипова с выводом содержимого pos в монитор, получил следующую статистику, при нажатии кнопки на странице происходит отправка 10 ТСР пакетов, а в монитор выводится два раза число 54. После анализа содержимого переданных пакетов первая мысль pos - содержит первый байт передаваемых данных в пакете, так как пакеты с данными (их всего два из 10) содержали число "54" но по адресу 0х0038, так как по идее данные должны начинаться с адреса 0х0036, этот вариант был отвергнут, перевел адрес 0х0036 в десятичную систему получил искомое "54", то есть адрес первого байта полезных данных.
Начал эксперементировать с участком кода,приведенным выше и о чудо получил ответ, но опять странный. Ответ появляется только если я отправляю больше 8-ми байт данных. И похоже получил подтверждение что приходит в pos адрес первого байта полезных данных. Потому что в коде нет функции подтверждения о получении пакета и с ПК он шлется несколько раз, сколько отправит столько и сообщений в мониторе.
Пока писал это сообщение на часть вопросов уже сам нашел ответ, но не факт что правильный, поэтому небольшой итог
По функциям:
word len = ether.packetReceive(); //как описано в библиотеке копирует принятые данные в буфер и возвращает длину пакета данных
word pos = ether.packetLoop(len); //как описано в библиотеке анализирует полученные данные определенной длины, возвращает адрес смещения полезных данных в пакете или ноль, если ничего нет или служебные данные, как выяснилось также возвращает ноль если длина данных меньши восьми байт.
Погружаясь глубже в библиотеку нашел участок кода этой функции в файле tcpip.cpp
if (tcp_client_state==3 && len>0)
{ //TCP connection established so read data
if (client_tcp_result_cb) {
uint16_t tcpstart = TCP_DATA_START; // TCP_DATA_START is a formula
if (tcpstart>plen-8)
tcpstart = plen-8; // dummy but save
uint16_t save_len = len;
if (tcpstart+len>plen)
save_len = plen-tcpstart;
(*client_tcp_result_cb)((gPB[TCP_DST_PORT_L_P]>>5)&0x7,0,tcpstart,save_len); //Call TCP handler (callback) function
Мне кажется ответ про восемь байт скрыт где-то здесь, особые подозрения вызывает последняя строчка, но не могу понять что в ней происходит, кто-нибудь может подсказать? и вопрос вызывает tcpstart, как она вычисляется, формулу то я нашел, но что в ней происходит не очень понял:
TCP_DATA_START ((uint16_t)TCP_SRC_PORT_H_P+(gPB[TCP_HEADER_LEN_P]>>4)*4)
Ну и еще один вопрос как работать с функцией вывода bfill.emit_p(), как выбрать параметры чтобы отправить один байт? А также как отправить подтверждение о получении ТСР пакета, а то клиент кидает 6-7 пакетов в ожидании ответа, а потом разрывает соединение?
Заранее спасибо!